mongodb update on JSON array - javascript

I have this data in Mongo:
{'_id':1,
'name':'Root',
'taskId':1,
'parentId':"",
'path':[1],
'tasks':[ {"taskId":3,parentId:1,name:'A',type:'task'},
{"taskId":4,parentId:1,name:'D',type:'task'},
{"taskId":5,parentId:4,name:'B',type:'task'},
{'type':'project' , 'proRef':2},
{"taskId":6,parentId:3,name:'E',type:'task'},
{"taskId":7,parentId:6,name:'C',type:'task'}]
}
Now I want to update taskId 6 with new Json data .
var jsonData = {"taskId":6,"name":'Sumeet','newField1':'Val1','newField2':'Val2'}
query should update if field is available else add new key to existing .Output Like
{"taskId":6,parentId:3,name:'Sumeet',type:'task','newField1':'Val1','newField2':'Val2'}]
I have tried few query but it is completely replacing json .
db.projectPlan.update({_id:1,'tasks.taskId':6},{$set :{'tasks.$':jsonData }});
Thanks in advance for your helps!
Sumeet

You need to transform the jsonData variable into something that can be passed to update. Here's an example that does exactly what you want with your sample document:
var updateData = {};
for (f in jsonData) {
if (f != "taskId") updateData["tasks.$."+f]=jsonData[f];
};
db.projectPlan.update({_id:1, 'tasks.taskId':6}, {$set:updateData})
Result:
{ "_id" : 1,
"name" : "Root",
"taskId" : 1,
"parentId" : "",
"path" : [ 1 ],
"tasks" : [
{ "taskId" : 3, "parentId" : 1, "name" : "A", "type" : "task" },
{ "taskId" : 4, "parentId" : 1, "name" : "D", "type" : "task" },
{ "taskId" : 5, "parentId" : 4, "name" : "B", "type" : "task" },
{ "type" : "project", "proRef" : 2 },
{ "taskId" : 6, "parentId" : 3, "name" : "Sumeet", "type" : "task", "newField1" : "Val1", "newField2" : "Val2" },
{ "taskId" : 7, "parentId" : 6, "name" : "C", "type" : "task" }
] }

You will need to merge the document manually:
var jsonData = {"taskId":5,"name":'Sumeet','newField1':'Val1','newField2':'Val2'};
db.projectPlan.find({ _id: 1 }).forEach(
function(entry) {
for (var taskKey in entry.tasks) {
if (entry.tasks[taskKey].taskId === jsonData.taskId) {
printjson(entry.tasks[taskKey]);
for (var taskSubKey in jsonData) {
entry.tasks[taskKey][taskSubKey] = jsonData[taskSubKey];
}
printjson(entry.tasks[taskKey]);
}
}
db.projectPlan.save(entry);
}
);
Obviously you can leave away the printjson statements. This is simply to see that the merging of the original tasks with the new tasks works. Note that this query will only update a single document as long as the _id field is unique.

Related

Access title inside id

I am having trouble to access title inside an ID object.
I want to access item.title. But i am not able to give a name to the object ID.
I tried doing order.cart.items.item.title
"_id" : ObjectId("5d60d1752cda6403e4f868af"),
"created_at" : ISODate("2019-08-24T05:55:34.741Z"),
"user" : ObjectId("5d60d00e4c865312ccf3f18a"),
"cart" : {
"items" : {
"5d60cddb69f460191c680e96" : {
"item" : {
"_id" : "5d60cddb69f460191c680e96",
"imagePath" : "https://dks.scene7.com/is/image/GolfGalaxy/18NIKWRMX270XXXXXLFS_Black_Cream?wid=1080&fmt=jpg",
"title" : "Nike ",
"description" : "Nike Airmax",
"price" : 10,
"category" : "shoes",
"__v" : 0
},
"qty" : 1,
"price" : 10
}
},
"totalQty" : 1,
"totalPrice" : 10
},
You need to use Object.values for that, because of the ID. This allows you to get the object with the key of 5d60cddb69f460191c680e96 without the key:
Object.values(order.cart.items)[0].item.title
const data = {
"cart" : {
"items" : {
"5d60cddb69f460191c680e96" : {
"item" : {
"_id" : "5d60cddb69f460191c680e96",
"imagePath" : "https://dks.scene7.com/is/image/GolfGalaxy/18NIKWRMX270XXXXXLFS_Black_Cream?wid=1080&fmt=jpg",
"title" : "Nike ",
"description" : "Nike Airmax",
"price" : 10,
"category" : "shoes",
"__v" : 0
},
"qty" : 1,
"price" : 10
}
},
"totalQty" : 1,
"totalPrice" : 10
}};
for (let id in data.cart.items)
console.log(data.cart.items[id].item.title);
You can simply achieve this by getting key name of an object using Object.keys() methods, This methods returns an array of key names
const obj = { id: 1 };
const keysArray = Object.keys(obj);
console.log(keysArray);. // ["id"]
In your case only one keys are present in the object, So we can directly get that name with index 0 (Object.keys(obj)[0])
Check below snippet
const cart ={
"items": {
"5d60cddb69f460191c680e96": {
"item": {
"_id":
"5d60cddb69f460191c680e96",
"imagePath": '',
"title": "Nike ",
"description": "Nike",
"price": 10,
"category": "shoes",
"__v": 0
},
"qty": 1,
"price": 10
}
}
};
const id =
Object.keys(cart.items)[0];
console.log(
cart.items[id].item.title
);

How to get aggregation of child collection in mongodb and apply $count is not working

I want to sum counts values for each beacon. I'm using aggregate query but it returns with counts 0. Please let me know if there is mistake in query.
Sample Data
[ {
"_id" : ObjectId("5a8166392aa41ec66efc66bf"),
"userID" : "5a7c3410bdff0f0014181874",
"date" : ISODate("2018-02-08T11:04:54.000Z"),
"beacons" : [
{
"counts" : "2",
"UUID" : "red"
},
{
"counts" : "1",
"UUID" : "blue"
}
]
},
{
"_id" : ObjectId("5a8166392aa41ec66efc66c0"),
"userID" : "5a7c3410bdff0f0014181874",
"date" : ISODate("2018-02-08T11:04:54.000Z"),
"beacons" : [
{
"counts" : "2",
"UUID" : "red"
},
{
"counts" : "1",
"UUID" : "blue"
}
]
}
]
Query
/* Query */
db.getCollection('CountsDetail')
.aggregate([
{
"$unwind":"$beacons"
},
{
"$group": {
"_id":"$beacons.UUID", "counts":{ "$sum":"$counts"}
}
}]);
Response
/* Response */
{
"_id" : "red",
"counts" : 0
}
{
"_id" : "blue",
"counts" : 0
}
Response is returning 0 in sum, which is weird. Please correct what I am doing wrong. Thanks
Sorry miss read your OP. Your counts field is nested so use a dot notation:
"counts":{ "$sum":"$beacons.counts"}

how to use value as key in mongodb

Given this as output of mongo find command
{
"cust" : NumberInt(8388),
"key" : "T_SUB_CAT",
"value" : "98",
"tag1" : "T_RECENT_SUB_CAT_1"
},{
"cust" : NumberInt(8388),
"key" : "T_SUB_CAT",
"value" : "109",
"tag1" : "T_RECENT_SUB_CAT_2"
},{
"cust" : NumberInt(8388),
"key" : "T_SUB_CAT",
"value" : "6",
"tag1" : "T_RECENT_SUB_CAT_3"
}
how to use aggregation and $project to get result like this
{
"cust" : NumberInt(8388),
"T_RECENT_SUB_CAT_1" : "98",
"T_RECENT_SUB_CAT_2" : "109",
"T_RECENT_SUB_CAT_3" : "6"
}
please help me using project / aggregate
thanks a lot
put all result in a var say cust2,
while(cust2.hasNext()){
var document = cust2.next(); db.<collection>.update(
{ cust: document.cust, tag1:document.tag1 },
{ cust:document.cust , tag1:document.tag1 ,
key:document.key, value:document.value },
{upsert:true}
) }

MongoDB Shell: How to Update a Collection from a Collection

I have two collections: links and children.
Links has values like this:
> db.links.find().pretty()
{ "_id" : ObjectId("567374999df36aeeda6f2a5f"), "EID" : 1, "CID" : 1 }
{ "_id" : ObjectId("567374999df36aeeda6f2a60"), "EID" : 1, "CID" : 3 }
{ "_id" : ObjectId("567374999df36aeeda6f2a61"), "EID" : 2, "CID" : 5 }
Children has values like this:
{
"_id" : ObjectId("567382709df36aeeda6f2a7e"),
"CID" : 2,
"Cname" : "Mo",
"Age" : 11
}
{
"_id" : ObjectId("567382709df36aeeda6f2a7f"),
"CID" : 3,
"Cname" : "Adam",
"Age" : 13
}
{
"_id" : ObjectId("567382709df36aeeda6f2a80"),
"CID" : 4,
"Cname" : "Eve",
"Age" : 21
}
It seems like this should add EID to children where CID matches between links and children, but it does nothing.
db.children.find().forEach(function (doc1) {
var doc2 = db.links.find({ id: doc1.CID });
if (doc2.CID == doc1.CID) {
doc1.EID = doc2.EID;
db.children.save(doc1);
}
});
This sets the value of EID in children to the value of EID from links where the value of CID in children == 14.
db.children.find().forEach(function (doc1) {
var doc2 = db.links.find({},{_id: 0, CID: 1});
if (doc1.CID == 14) {
doc1.EID = doc1.CID;
db.children.save(doc1);
}
});
{
"_id" : ObjectId("567382709df36aeeda6f2a8a"),
"CID" : 14,
"Cname" : "George II",
"Age" : 12,
"EID" : 14
}
So, it seems like that the equality operation in Javascript (doc2.CID == doc1.CID) isn't working. Why won't this work? I assume I have the syntax wrong or am using the wrong equality operation or operator?
var doc2 = db.links.find({ id: doc1.CID });
doc2 here is a cursor, not the document itself. So you need to go through documents in the cursor.
Try the following code:
db.children.find().forEach(function (doc1) {
var doc2 = db.links.find({CID:doc1.CID}).forEach(function(doc2){
doc1.EID = doc2.EID;
db.children.save(doc1);
})
})

object transformation with underscore.js

For whatever reason, I have quite a bit of difficulty when trying to transform objects and arrays.
The current data I have is stored in a mongodb collection and looks like this:
[{ "_id" : 1, "name" : "someName", "colorName" : "Pink"},
{ "_id" : 2, "name" : "someName2", "colorName" : "RoyalBlue"},
{ "_id" : 3, "name" : "aThirdOne", "colorName" : "Gold"},
{ "_id" : 4, "name" : "oneMore", "colorName" : "LightGreen"}]
I need to get either the following two arrays, but would like to know how to get both.
[{ "value" : 1, "label" : "someName"},
{ "value" : 2, "label" : "someName2"},
{ "value" : 3, "label" : "aThirdOne"},
{ "value" : 4, "label" : "oneMore"]
[{1 : "someName"},
{2 : "someName2"},
{3 : "aThirdOne"},
{4 : "oneMore"}]
I know it is probably something with _.map, but I am not sure why I can't figure it out. Please advise.
You don't really need Underscore for this, it's just normal Array.prototype.map method usage (although Underscore also provides this method):
var data = [{ "_id" : 1, "name" : "someName", "colorName" : "Pink"},
{ "_id" : 2, "name" : "someName2", "colorName" : "RoyalBlue"},
{ "_id" : 3, "name" : "aThirdOne", "colorName" : "Gold"},
{ "_id" : 4, "name" : "oneMore", "colorName" : "LightGreen"}];
var result = data.map(function(el, i) {
return {value: el._id, label: el.name};
});
document.body.innerHTML = '<pre>' + JSON.stringify(result, null, 4) + '</pre>';
Also note, that your second data structure doesn't make sense because it's irregular, so don't use it, it's not very convenient at all.
And here is corresponding Underscore version:
// Or Underscore version
var result = _.map(data, function(el) {
return {value: el._id, label: el.name};
});
In plain Javascript you can use Array.prototype.forEach() for iteration througt the array and assembling the objects and push it to the wanted results.
The forEach() method executes a provided function once per array element.
var array = [{ "_id": 1, "name": "someName", "colorName": "Pink" }, { "_id": 2, "name": "someName2", "colorName": "RoyalBlue" }, { "_id": 3, "name": "aThirdOne", "colorName": "Gold" }, { "_id": 4, "name": "oneMore", "colorName": "LightGreen" }],
result1 = [],
result2 = [];
array.forEach(function (a) {
result1.push({ value: a._id, label: a.name });
var o = {};
o[a._id] = a.name
result2.push(o);
});
document.write('<pre>' + JSON.stringify(result1, 0, 4) + '</pre>');
document.write('<pre>' + JSON.stringify(result2, 0, 4) + '</pre>');
use:
var newObject = _.map(yourObject, function(val) {
return {
"value": val._id,
"label": val.name
}});
And the same concept for the other result you're interested in .

Categories

Resources