Pass json array to http flutter - flutter

I am trying to integrate this add stock feature into the app,but i am kind of stuck how do pass those incremented items data to http package,i have made view and shows data just like this
please checkout entire code for this process
https://github.com/Abhijithsp/flutter-image_upload/blob/master/Add%20Stocks.dart
Process
How do i pass the data just like this
{
"id" : "", //NOT NULL IF EDIT
"station_id": 2,
"name" : "Test Stocks",
"unit" : "1", (DROPDOWN) ==>1 UNITS
"branches" : [{
"branch_id": 87,
"kg" : 10,
"gm" : 5,
"ltr" : 0,
"ml" : 0,
"counter" : 0
},{
"branch_id": 88,
"kg" : 10,
"gm" : 8,
"ltr" : 0,
"ml" : 0,
"counter" : 0
},
]
}

You can use list_branch_details along with its StockBranchDetailsModel store inside it for every rows. and whenever any change in data the you can save to particular position of that list named list_branch_details and while sending data
var data ={};
var branches=[];
var branch ={};
data["name"] = "Test Stocks";
data["unit"] = "1";
for(int i =0;i< list_branch_details.length; i++ ) {
branch = {};
branch["branch_id"] = list_branch_details.get(i).getBranchId();
branch["kg"] = list_branch_details.get(i).getKg();
branches.add(branch);
}
data["branches"] = branches;
and just encode it.
jsonEncode(data);

Related

Groovy: Retrieve a value from a JSON based on an object

So I have a JSON that looks like this
{
"_embedded" : {
"userTaskDtoList" : [
{
"userTaskId" : 8,
"userTaskDefinitionId" : "JJG",
"userRoleId" : 8,
"workflowId" : 9,
"criticality" : "MEDIUM",
**"dueDate"** : "2021-09-29T09:04:37Z",
"dueDateFormatted" : "Tomorrow 09:04",
"acknowledge" : false,
"key" : 8,
},
{
"userTaskId" : 10,
"userTaskDefinitionId" : "JJP",
"userRoleId" : 8,
"workflowId" : 11,
"criticality" : "MEDIUM",
**"dueDate"** : "2021-09-29T09:06:44Z",
"dueDateFormatted" : "Tomorrow 09:06",
"acknowledge" : false,
"key" : 10,
},
{
"userTaskId" : 12,
"userTaskDefinitionId" : "JJD",
"userRoleId" : 8,
"workflowId" : 13,
"criticality" : "MEDIUM",
**"dueDate"** : "2021-09-29T09:59:07Z",
"dueDateFormatted" : "Tomorrow 09:59",
"acknowledge" : false,
"key" : 12,
}
]
}
}
It's a response from a REST request. What I need is to extract the data of key "dueDate" ONLY from a specific object and make some validations with it. I'm trying to use Groovy to resolve this.
The only thing I've managed to do is this:
import groovy.json.*
def response = context.expand( '${user tasks#Response}' )
def data = new JsonSlurper().parseText(response)
idValue = data._embedded.userTaskDtoList.dueDate
Which returns all 3 of the values from the "dueDate" key in the response.
I was thinking that maybe I can interact with a certain object based on another key, for instance let's say I retrieve only the value from the "dueDate" key, that is part of the object with "userTaskId" : 12.
How could I do this?
Any help would be greatly appreciated.
You can find the record of interest, then just grab the dueDate from that
data._embedded.userTaskDtoList.find { it.userTaskId == 12 }.dueDate

How to update an array, by inserting an element at the first position

I want to update a document by adding a new element at the first position, in an array.
What I'm actually doing :
val updateRequest = myCollection.findOneAndUpdate(and(equal("site_id", new ObjectId(siteId)),and(equal("image_name", imageName))),
addToSet("url_history", urlHistory))
The result :
{
"_id" : ObjectId("5e297ea0c7ede90a7ae7586e"),
"image_name" : "test.jpg",
"url_history" : [
{
"date" : ISODate("2020-02-08T10:43:47.127Z"),
"url" : "No image url"
},
{
"date" : ISODate("2020-02-11T10:43:47.127Z"),
"url" : "test.jpg"
}
]
}
The desired result :
{
"_id" : ObjectId("5e297ea0c7ede90a7ae7586e"),
"image_name" : "test.jpg",
"url_history" : [
{
"date" : ISODate("2020-02-11T10:43:47.127Z"),
"url" : "test.jpg"
},
{
"date" : ISODate("2020-02-08T10:43:47.127Z"),
"url" : "No image url"
}
]
}
Have you tried the "$position" operator? Take a look https://docs.mongodb.com/manual/reference/operator/update/position/
Using mongoose would be like this:
const schema = Schema({ nums: [Number] });
const Model = mongoose.model('Test', schema);
const doc = await Model.create({ nums: [3, 4] });
doc.nums.push(5); // Add 5 to the end of the array
await doc.save();
// You can also pass an object with `$each` as the
// first parameter to use MongoDB's `$position`
doc.nums.push({
$each: [1, 2],
$position: 0
});
doc.nums; // [1, 2, 3, 4, 5]
from mongoose docs
And do you really need to insert it in the first position? Maybe is a good idea to preserve the array order and when you fetch its values you can just order by the way you desire, what do you think about it?
I finally found a solution !
Here it is :
val updateRequest = myCollection.findOneAndUpdate(and(equal("site_id", new ObjectId(siteId)),and(equal("image_name", imageName))),
pushEach("url_history", PushOptions().position(0), urlHistory))
I used the PushOptions.
Hope it helps.
Source :
https://mongodb.github.io/mongo-scala-driver/2.6/scaladoc/org/mongodb/scala/model/Updates$.html

Meteor Methods insert not working (mongodb)

I am trying to write a table with various numbers of rows and columns to a database. For this, I have a Criterion collection that saves the table headers and an Option collection that saves the table data.
The structure is like this:
for Criterion:
{
{ "_id" : "hId1", "name" : "Option Name", "tableId" : "tId1" },
{ "_id" : "hId2", "name" : "Rent", "score" : 9, "tableId" : "tId1" },
{ "_id" : "hId3", "name" : "Surface", "score" : 5, "tableId" : "tId1" },
{ "_id" : "hId4", "name" : "Price", "score" : 5, "tableId" : "tId1" },
{ "_id" : "hId5", "name" : "CPU", "score" : 5, "tableId" : "tId4" }
etc.
}
for Option:
{
{ "_id" : "id1", "score" : 5,
"hId1" : { "value" : "Apt 1" },
"hId2" : { "value" : "800 sqft", "score" : 1 },
"hId3" : { "value" : "$800", "score" : 3 },
etc.
"tableId" : "tId1"
}
{ "_id" : "id2", "score" : 5,
"hId1" : { "value" : "Apt 2" },
"hId2" : { "value" : "780 sqft", "score" : 10 },
"hId3" : { "value" : "$700", "score" : 3 },
etc.
"tableId" : "tId1"
}
etc.
}
The first row for Criterion will always have "Option Name". For the data above, the table with "tableId" = "tId1" would end up looking like this (tableId and headerId are the keys):
| Option Name | Surface | Price |
| =========== | ======== | ===== |
| Apt 1 | 800 sqft | $800 |
| Apt 2 | 780 sqft | $700 |
My code looks like this (imports/api/comparison.js):
/**
* Options are for the rows
*/
export var Option = new Mongo.Collection('option');
/**
* Criteria are the columns
*/
export var Criterion = new Mongo.Collection('criterion');
Meteor.methods({
'comparison.insertRow' (query, headerId, tableId, isFirst) {
check(query, Object);
check(headerId, String);
check(tableId, String);
check(isFirst, Boolean);
if(isFirst){
var data = {};
data._id = headerId;
data.tableId = tableId;
data.name = "Option Name";
Criterion.insert(data);
}
query._id = tableId;
Option.insert(query);
},
});
Where isFirst is a boolean expressing whether this is the first row in a table or not.
My query is constructed like this (imports/ui/Menu/DataInsert.jsx):
var query = {};
query.score = // value
// get the header separately
query[headerId] = {
value: //valueH from form
};
// Find the text field via the React ref
for (var i = 1, len = cols.length; i < len; i++) {
query[cols[i]._id] = {
value: //valueV from form,
score: //valueS from form
};
}
My files are available on the server because I am doing this in server/main.js: import '../imports/api/comparison.js';
The query gets inserted no problem into Option no problem.
Why isn't data getting inserted into Criterion (when isFirst = true)?
I did a console.log(data) and a console.log(query) and it looks like this:
whereas the data in the db looks like this:
#jordanwillis was correct above, this was happening because I was setting the _id manually on the query. I did need to set the id, but I needed to set the tableId.
So, for the record, this is what I did:
'comparison.insertRow' (query, headerId, tableId, isFirst) {
check(query, Object);
check(headerId, String);
check(tableId, String);
check(isFirst, Boolean);
if(isFirst){
var data = {};
data._id = headerId;
data.tableId = tableId;
data.name = "Option Name";
Criterion.insert(data);
}
query.tableId = tableId;
Option.insert(query);
},
And my foreign keys are tableId and headerId (which is part of query).

Querying with array of parameters in mongodb

I have below collection in the DB, I want to retrieve data where birth month equal to given 2 months. lets say [1,2], or [4,5]
{
"_id" : ObjectId("55aa1e526fea82e9a4188f38"),
"name" : "Nilmini",
"birthDate" : 6,
"birthMonth" : 1
},
{
"_id" : ObjectId("55aa1e526fea82e9a4188f39"),
"name" : "Ruwan",
"birthDate" : 6,
"birthMonth" : 1
},{
"_id" : ObjectId("55aa1e526fea82e9a4188f40"),
"name" : "Malith",
"birthDate" : 6,
"birthMonth" : 1
},
{
"_id" : ObjectId("55aa1e526fea82e9a4188f7569"),
"name" : "Pradeep",
"birthDate" : 6,
"birthMonth" : 7
}
I use below query to get the result set, I could get the result for give one month,now I want to get results for multiple months.
var currentDay = moment().date();
var currentMonths = [];
var currentMonth = moment().month();
if(currentDay > 20){
currentMonths.push(moment().month());
currentMonths.push(moment().month()+1);
}else{
currentMonths.push(currentMonth);
}
// In blow query I am trying to pass the array to the 'birthMonth',
I'm getting nothing when I pass array to the query, I think there should be another way to do this,
Employee.find(
{
"birthDate": {$gte:currentDay}, "birthMonth": currentMonths
}, function(err, birthDays) {
res.json(birthDays);
});
I would really appreciate if you could help me to figure this out
You can use the $in operator to match against multiple values in an array like currentMonths.
So your query would be:
Employee.find(
{
"birthDate": {$gte:currentDay}, "birthMonth": {$in: currentMonths}
}, function(err, birthDays) {
res.json(birthDays);
});

mongodb mapreduce exclude nested field

I am mongodb newbie! I am trying to process some tweeter data. my goal is to group users on each time interval (for simplicity, daily interval) and count his unique hashtags on that day. My idea to build new DB which is only contains user, date and hashtags. Here is data format:
> db.sampledDB.findOne()
{
"_id" : NumberLong("2334234"),
"replyid" : NumberLong(-1),
"userid" : NumberLong(21313),
"replyuserid" : NumberLong(-1),
"createdAt" : ISODate("2013-07-02T22:35:06Z"),
"tweettext" : "RT #BBCBreaking: Plane carrying Bolivia President Morales is diverted to Austria on suspicion US fugitive #Snowden is on board - Bolivian m…",
"screenName" : "x83",
"name" : "david x",
"retweetCount" : NumberLong(0),
"retweet_id" : NumberLong("12313223"),
"retweet_userid" : NumberLong(123123123),
"source" : "Twitter for Windows Phone",
"hashtags" : [
{
"start" : 106,
"end" : 114,
"text" : "Snowden"
}
],
"mentions" : [
{
"start" : 3,
"end" : 15,
"id" : NumberLong(876678),
"screenName" : "BBCBreaking",
"name" : "BBC Breaking News"
}
],
"media" : [ ]
}
I use mapReduce like this:
MAP:
map = function(){
//format date to year/month/day
var format = this.createdAt.getFullYear() + '/' + (this.createdAt.getMonth()+1) + '/' + this.createdAt.getDate();
var key = {userid:this.userid, date:format};
emit(key,{hashtags:this.hashtags}); }
REDUCE:
reduce = function(key,values){
var result = {a:[]};
for (var idx=0;idx<values.length;idx++){
result.a.push(values[idx].hashtag);
}
return result};
it results to:
{
"_id" : {
"userid" : NumberLong(7686787),
"date" : "2013/7/5"
},
"value" : {
"hashtag" : [
{
"start" : 24,
"end" : 44,
"text" : "SıkSöylenenYalanlar"
},
{
"start" : 45,
"end" : 60,
"text" : "ZimmermanTrial"
},
{
"start" : 61,
"end" : 84,
"text" : "ZaynMalikYouArePerfect"
},
{
"start" : 85,
"end" : 99,
"text" : "TrayvonMartin"
},
{
"start" : 100,
"end" : 110,
"text" : "Wimbledon"
},
{
"start" : 111,
"end" : 118,
"text" : "Футбол"
},
{
"start" : 119,
"end" : 127,
"text" : "Snowden"
},
{
"start" : 128,
"end" : 138,
"text" : "TFFistifa"
}
]
}
},
{
"_id" : {
"userid" : NumberLong(45666),
"date" : "2013/7/5"
},
"value" : {
"hashtag" : [
{
"start" : 24,
"end" : 44,
"text" : "SıkSöylenenYalanlar"
},
{
"start" : 45,
"end" : 60,
"text" : "ZimmermanTrial"
},
{
"start" : 61,
"end" : 84,
"text" : "ZaynMalikYouArePerfect"
},
{
"start" : 85,
"end" : 99,
"text" : "TrayvonMartin"
},
{
"start" : 100,
"end" : 110,
"text" : "Wimbledon"
},
{
"start" : 111,
"end" : 118,
"text" : "Футбол"
},
{
"start" : 119,
"end" : 127,
"text" : "Snowden"
},
{
"start" : 128,
"end" : 138,
"text" : "TFFistifa"
}
]
}
},
But I just want to keep the text element of hashtags. I tried to change the reducer to values[idx].hashtag.text or values[idx].hashtag["text"] which did not help.
UPDATE:
I suspect my problem is similar to MapReduce problem, but I dont know to fix mine
You might also consider using the aggregation framework which can produce the results shown below. The pipeline would look similar to this:
{$project: {
userid: "$userid",
"hashtags": "$hashtags.text",
date: {
year: { $year: "$createdAt" },
month: { $month: "$createdAt"},
day: {$dayOfMonth: "$createdAt"} }}},
{$unwind: "$hashtags" },
{ $group: { _id : {
date: "$date",
userid: "$userid"},
hashtags: { $addToSet:"$hashtags" }
}} )
Might produce a result like:
[
{
"_id" : {
"date" : {
"year" : 2013,
"month" : 8,
"day" : 4
},
"userid" : NumberLong(362337301)
},
"hashtags" : [
"tagger",
"stackoverflow",
"twitter"
]
}, /* more */
A brief explanation of the aggregation framework pipeline:
Using $project, grab only the fields that will matter through the rest of the pipeline. Before doing this, if there was a specific date or range that would have been desired, using $match would have been a great step to filter some of the results efficiently). Note that the createdAt field has been split into the respective pieces so that the time of day will later be ignored when grouping. After the projection has occurred, the new field will be called date in the example. Here, the hash tags have been simplified to be only the text property, and the name reused as "hashtags".
Next, as "hashtags" is an array at this point (would look like: ['tagger', 'stackoverflow', 'twitter'] for example, the pipeline creates a new document for each element in the "hashtag" array.
Finally, the grouping pipeline operator uses the combination of userid and date as a grouper, and adds all unique hash tags to a field called "hashtags".
As an alternative to splitting the date, you can also just treat the createdAt field as a string, and remove the time by using this in the pipeline:
date: {$substr: ["$createdAt",0, 10] }
It would produce something like:
2013-07-02
Edit
As you've pointed out, there is currently a 16MB limit in the document that is output from an Aggregation. While this is scheduled to be changed in the 2.6 version of MongoDB, you may be able to get a MapReduce as well that work. It's a bit messier given a MapReduce wasn't necessarily intended for this type of work, so the results may not be necessarily what you want.
map = function() {
var format = this.createdAt.getFullYear() + '/'
+ (this.createdAt.getMonth()+1) + '/' + this.createdAt.getDate();
var key = {userid:this.userid, date:format};
var hashtags = this.hashtags || [];
for(var i=0, l=hashtags.length; i < l; i++) {
emit(key, hashtags[i].text);
}
};
reduce = function(key, values){
values = values || [];
var tag;
var tags = {};
for(var i=0, l=values.length; i<l ; i++) {
tag = values[i] || "";
if (tag.length > 0) {
tags[tag] = "";
}
};
values = [];
for(var t in tags) {
values.push(t);
}
return values.join(',');
};
Instead of emitting the array, it emits each hash tag in the map. The reduce eliminates duplicates using a simple associative array and then returns a joined string with all of the hash tags. MongoDB does not support returning an array of results via the reduce function (the idea is that a reduce should be providing one result, not an array of results).
Results:
{
"_id" : {
"userid" : NumberLong(262317302),
"date" : "2013/7/2"
},
"value" : "Wisconsin,Space,Cheese"
}
If you don't need to do this work frequently, you could also just write a shell script in the MongoDB console that extracts the hash tags into a new collection. Then, just run it when you need to.
here is how I managed to produce the same result as the answer above. just for presenting another solution.
map = function(){
var day = this.createdAt.getFullYear() + '/' + (this.createdAt.getMonth()+1) + '/' + this.createdAt.getDate();
var key = {userid:this.userid, date:day};
var values = {hashtags:[]};
for (var idx=0;idx<this.hashtags.length;idx++){
values.hashtags.push(this.hashtags[idx].text);
}
emit(key,values);
};
reduce = function(key,values){
hashtag_list = {hashtags: []} ;
for(var i in values) {
hashtag_list.hashtags= values[i].hashtags.concat(hashtag_list.hashtags);
}
return hashtag_list;
}
Try:
values[idx].text
hashtag is not a property of the object, but text is.