how to use value as key in mongodb - javascript

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}
) }

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 go through JSON data to create a list, even the children?

I have a JSON object that I need to create a list out of.
I would be able to do it fine but each object can have children. It looks something like this :
{
"Boys" :
[
{
"name" : "Fred",
"age" : "65",
"children" : [{
"name" : "dave",
"age" : "24",
"children" : []
}, {
"name" : "cliff",
"age" : "32",
"children" : []
}
]
},
{
"name" : "jon",
"age" : "46",
"children" : [{
"name" : "jess",
"age" : "26",
"children" : []
}, {
"name" : "gloria",
"age" : "19",
"children" : []
}
]
}
],
"Girls" :
[
{
"name" : "Jane",
"age" : "65",
"children" : [{
"name" : "dave",
"age" : "24",
"children" : []
}, {
"name" : "grace",
"age" : "32",
"children" : []
}
]
},
{
"name" : "ariana",
"age" : "46",
"children" : [{
"name" : "jessy",
"age" : "28",
"children" : []
}, {
"name" : "niki",
"age" : "19",
"children" : []
}
]
}
]
}
I'd be able to go through it fine in a for-loop but I'm unsure how to go through the children too.
Basically I want to go through each element and create a list item with the text being the name of the object I am currently at.
So for the JSON above it would be something like :
-Boys
-Fred
-Dave
-Cliff
-Jon
-Jess
-Gloria
-Girls
-Jane
-Dave
-Grace
-Ariana
-Jessy
-Niki
After I create this list I will be using JSTree to format it, any help is appreciated :)
You need a recursive function, a function that calls itself until something happens. In your case, you need a function that goes through a list of people. For each person, it'd paint the name, then would check if that person has children. If it does, then calls the function again, passing it the list of children.
Something like this:
var renderList = function(list){
var $list = $('<ul>');
$.each(list, function(i, element){
var $child = $('<li>'+element.name+'</li>');
if (element.children.length > 0) {
$child.append(renderList(element.children));
}
$list.append($child);
});
return $list;
};
$('#boys').append(renderList(data.Boys)); // Start list of boys
$('#girls').append(renderList(data.Girls)); // Start list of girls
Working example here http://jsfiddle.net/zbm778ag/

mongodb update on JSON array

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.

Map Reduce for MongoDB

I have a collection in which each object contains details of the user along with the comments user has given on specific products which is given below
{
"_id" : ObjectId("51efcbc8786df13540e46887"),
"value": {
"UserDetails" : [
[
{
"country" : "CA",
"gender" : "M",
"age" : "18",
"userIdtemp" : ObjectId("51efcbc8786df13540e46887")
}
]
],
"comments" : [
{
"commentId" : ObjectId("51efcc41786df13540e46891"),
"comment" : "Hey, what's up?",
"created" : ISODate("2013-07-24T12:44:49.400Z"),
"productId" : ObjectId("51efcbd4786df13540e4688c"),
"userId" : ObjectId("51efcbc8786df13540e46887")
},
{
"commentId" : ObjectId("51efcc43786df13540e46893"),
"comment" : "Cool",
"created" : ISODate("2013-07-24T12:44:51.004Z"),
"productId" : ObjectId("51efcbd2786df13540e4688b"),
"userId" : ObjectId("51efcbc8786df13540e46887")
}
]
}
}
{
"_id" : ObjectId("51efcbc8786df13540e46888"),
"value" : {
"UserDetails" : [
[
{
"country" : "US",
"gender" : "M",
"age" : "25",
"userIdtemp" : ObjectId("51efcbc8786df13540e46888")
}
]
],
"comments" : [
{
"commentId" : ObjectId("51efcc41786df13540e46892"),
"comment" : "Not much",
"created" : ISODate("2013-07-24T12:44:49.475Z"),
"productId" : ObjectId("51efcbd4786df13540e4688c"),
"userId" : ObjectId("51efcbc8786df13540e46888")
}
]
}
}
{
"_id" : ObjectId("51efcbc8786df13540e46889"),
"value" : {
"UserDetails" : [
{
"country" : "US",
"gender" : "F",
"age" : "13",
"userIdtemp" : ObjectId("51efcbc8786df13540e46889")
}
]
}
}
I have to extract comments separately along with there userDetails with key as productId so i have written map something like following
mapCommentsFrom = function(){
if("comments" in this.value)
{
for(var idx = 0;idx<this.value.comments.length;idx++){
var key = this.value.comments[idx].productId;
var value = [{
commentId: this.value.comments[idx].commentId,
comment:this.value.comments[idx].comment,
created:this.value.comments[idx].created,
productId:this.value.comments[idx].productId,
userId:this.value.comments[idx].userId,
country:this.value.UserDetails[0][0].country,
gender:this.value.UserDetails[0][0].gender,
age : this.value.UserDetails[0][0].age
}]
}
}
emit(key,value);
}
reduceFrom = function(k,values){
return values;
}
but where ever the number of comments are more than one i am getting only the last comment along with user details and other's key as well as value is coming null. Something like this
{ "_id" : null, "value" : null }
{
"_id" : ObjectId("51efcbd2786df13540e4688b"),
"value" : [
{
"length" : 2,
"commentId" : ObjectId("51efcc43786df13540e46893"),
"comment" : "Cool",
"created" : ISODate("2013-07-24T12:44:51.004Z"),
"productId" : ObjectId("51efcbd2786df13540e4688b"),
"userId" : ObjectId("51efcbc8786df13540e46887"),
"country" : "CA",
"gender" : "M",
"age" : "18"
}
]
}
{
"_id" : ObjectId("51efcbd4786df13540e4688c"),
"value" : [
{
"length" : 1,
"commentId" : ObjectId("51efcc41786df13540e46892"),
"comment" : "Not much",
"created" : ISODate("2013-07-24T12:44:49.475Z"),
"productId" : ObjectId("51efcbd4786df13540e4688c"),
"userId" : ObjectId("51efcbc8786df13540e46888"),
"country" : "US",
"gender" : "M",
"age" : "25"
}
]
}
Can somebody please help me as to what i am missing?
Thanks for help in advance
I cannot add comments due to reputation. But had you considered using the aggregation framework.
The $unwind operator will return you an array of sub documents quite easily and it's faster than using map/reduce.
I'm not sure it will exactly do what you're looking for but may help.
Take a look, http://docs.mongodb.org/manual/reference/aggregation/unwind/
Its because you are not emitting them in the map function.
Move the emit function inside the for loop.
mapCommentsFrom = function(){
if("comments" in this.value){
for(var idx = 0;idx<this.value.comments.length;idx++){
var key = this.value.comments[idx].productId;
var value = {
commentId: this.value.comments[idx].commentId,
comment:this.value.comments[idx].comment,
created:this.value.comments[idx].created,
productId:this.value.comments[idx].productId,
userId:this.value.comments[idx].userId,
country:this.value.UserDetails[0][0].country,
gender:this.value.UserDetails[0][0].gender,
age : this.value.UserDetails[0][0].age
}
emit(key,value);
}
}
}
Then you may also need to rewrite your reduce function to something like this
reduceFrom = function(k,valueArray){
var returnData = { values : [] } ;
for(var i=0;i<valueArray.length;i++)
returnData.values.push(valueArray[i]);
return returnData;
}
By far the easiest is to just use the aggregation framework for this. The aggregation framework allows you to execute operators on data, there is $match for doing queries (like find()) and various others. See for more information: http://docs.mongodb.org/manual/core/aggregation/
The aggregation framework also has an $unwind function that does exactly what you want. You use it like:
db.collection.aggregate( [
{ $unwind: '$value.comments' },
{ $project: {
_id: '$value.comments.productId',
value: 1
} }
] );
On your sample documents, this returns:
{
"result" : [
{
"_id" : ObjectId("51efcbd4786df13540e4688c"),
"value" : {
"UserDetails" : [
[
{
"country" : "CA",
"gender" : "M",
"age" : "18",
"userIdtemp" : ObjectId("51efcbc8786df13540e46887")
}
]
],
"comments" : {
"commentId" : ObjectId("51efcc41786df13540e46891"),
"comment" : "Hey, what's up?",
"created" : ISODate("2013-07-24T12:44:49.400Z"),
"productId" : ObjectId("51efcbd4786df13540e4688c"),
"userId" : ObjectId("51efcbc8786df13540e46887")
}
}
},
{
"_id" : ObjectId("51efcbd2786df13540e4688b"),
"value" : {
"UserDetails" : [
[
{
"country" : "CA",
"gender" : "M",
"age" : "18",
"userIdtemp" : ObjectId("51efcbc8786df13540e46887")
}
]
],
"comments" : {
"commentId" : ObjectId("51efcc43786df13540e46893"),
"comment" : "Cool",
"created" : ISODate("2013-07-24T12:44:51.004Z"),
"productId" : ObjectId("51efcbd2786df13540e4688b"),
"userId" : ObjectId("51efcbc8786df13540e46887")
}
}
},
{
"_id" : ObjectId("51efcbd4786df13540e4688c"),
"value" : {
"UserDetails" : [
[
{
"country" : "US",
"gender" : "M",
"age" : "25",
"userIdtemp" : ObjectId("51efcbc8786df13540e46888")
}
]
],
"comments" : {
"commentId" : ObjectId("51efcc41786df13540e46892"),
"comment" : "Not much",
"created" : ISODate("2013-07-24T12:44:49.475Z"),
"productId" : ObjectId("51efcbd4786df13540e4688c"),
"userId" : ObjectId("51efcbc8786df13540e46888")
}
}
}
],
"ok" : 1
}

Categories

Resources