I have several hundred thousands of documents in mongoDB to update.
here is an example of existing documents from collection Users:
{
"_id" : "549120bcf5115900124fb6e1",
"user" : "Tom",
"country" : "United Kingdom",
"province" : "North Yorkshire",
"city" : "York",
"organization" : ""
},
{
"_id" : "143184fbf5482260184ac6e2",
"user" : "Jack",
"country" : "Not Listed",
"province" : "",
"city" : "",
"organization" : "United Nations"
},
{
"_id" : "1234567890123456748979",
"user" : "Sarah",
"country" : "Not Listed",
"province" : "",
"city" : "",
"organization" : ""
},
{
"_id" : "98765432411654987654",
"user" : "Mat"
}
Each document has the possibility to have values in these fields :
a country, a province, and a city
or a country and a state
and here is the sample from another collection Countries:
{
"_id" : "123456789",
"key" : "Not Listed",
"uuid" : "ca55b53a-ef5b-43ed-90ed-b857f45ddb6d",
"organization" : [
{
"key" : "United Nations",
"uuid" : "1c4ae4c6-00c5-405d-98fa-ca7cc9edc72a"
},
{
"key" : "FIFA",
"uuid" : "11cfe606-821f-40fb-b1d0-bb7f9abb21dc"
}
],
"province" : [],
},
{
"_id" : "1123465498742",
"key" : "United Kingdom",
"uuid" : "d756e167-25ec-4aa9-b231-4dbf6d4bfce4",
"organization" : [],
"province" : [
{
"key" : "North Yorkshire",
"uuid" : "73d07c77-eba4-4dfa-9ada-e0ba8d8a2d55",
"city" : [
{
"key" : "York",
"uuid" : "80fd18a6-c4eb-4fb9-b591-6cca62319ba7"
},
{
"key" : "Middlesbrough",
"uuid" : "26a277c4-8640-4959-a64a-00f3727975f4"
}
],
},
{
"key" : "Oxfordshire",
"uuid" : "f7b5a570-df42-4520-ba3a-8bdcdd00e7d4",
"city" : [
{
"key" : "Oxford",
"uuid" : "b931865c-a363-4958-b7e7-5503fe674eb0"
},
{
"key" : "Banbury",
"uuid" : "b8d4c63a-75a9-4c3c-a4cd-d315f06a92e0"
}
],
}
]
}
The idea is to look up the country/organization/province/city field value from documents in Users collection and update them based on the uuid value of the Countries collection.
So the result will look like something like this:
{
"_id" : "549120bcf5115900124fb6e1",
"user" : "Tom",
"country" : "d756e167-25ec-4aa9-b231-4dbf6d4bfce4", // uuid of United Kingdom
"province" : "73d07c77-eba4-4dfa-9ada-e0ba8d8a2d55", // uuid of North Yorkshire
"city" : "80fd18a6-c4eb-4fb9-b591-6cca62319ba7", // uuid of York
"state" : ""
},
{
"_id" : "143184fbf5482260184ac6e2",
"user" : "Jack",
"country" : "ca55b53a-ef5b-43ed-90ed-b857f45ddb6d", // uuid of Not Listed
"province" : "",
"city" : "",
"state" : "1c4ae4c6-00c5-405d-98fa-ca7cc9edc72a" // uuid of United Nations
},
{
"_id" : "1234567890123456748979",
"user" : "Sarah",
"country" : "ca55b53a-ef5b-43ed-90ed-b857f45ddb6d", // uuid of Not Listed
"province" : "",
"city" : "",
"state" : ""
},
{
"_id" : "98765432411654987654",
"user" : "Mat"
}
The dependency of the fields are the following:
Country > Province > City
Or:
Country > Organization
It is possible that a parent field exists, but its child field doesn't exist or is empty.
How can I update these multidimensional arrays using mongo script rules?
Here is my attempt, but this is a lot of for loops, and not sure how to do the mongodb find/update/save part.. could somebody help to achieve it?
var usrCountry, uuidcountry, usrProvince, uuidprovince, usrOrg, uuidorg, usrCity, uuidcity;
for (var i = 0; i < users.length; i++) {
usrCountry = users[i].country;
usrProvince = users[i].province;
usrOrg = users[i].organization;
usrCity = users[i].city;
for (var j = 0; j < countries.length; j++) {
if (countries[j].key === usrCountry) {
uuidcountry = countries[j].uuid;
console.log('uuidcountry: ', uuidcountry)
if (countries[j].province.length){
for (var k = 0; k < countries[j].province.length; k++) {
if (countries[j].province[k].key === usrProvince){
uuidprovince = countries[j].province[k].uuid;
console.log('uuidprovince', uuidprovince)
for (var l = 0; l < countries[j].province[k].city.length; l++) {
if (countries[j].province[k].city[l].key === usrCity){
uuidcity = countries[j].province[k].city[l].uuid
console.log('uuidcity: ', uuidcity)
}
}
}
}
}
}
}
}
You can try do this with aggregation pipeline, and use that info to update
db.u.aggregate(
[
{
$lookup: {
from : "c",
localField : "country",
foreignField : "key",
as : "countryInfo"
}
},
{
$project: {
"_id" : 1,
"user" : 1,
"province" : 1,
"country" : 1,
"city" : 1,
"organization" : 1,
"country_uuid" : {$arrayElemAt : ["$countryInfo.uuid",0]},
"province_uuid" : { $arrayElemAt : [{ $map : { input : { $filter : { input : {$arrayElemAt : ["$countryInfo.province" ,0 ]} , as : "pro", cond : { $eq : [ "$$pro.key", "$province" ] } } } , as : "pr", in : "$$pr.uuid" } }, 0 ] },
"city_uuid" : {$arrayElemAt : [{$map : { input : { $arrayElemAt : [ {$filter : { input : { $map : { input : { $arrayElemAt : ["$countryInfo.province.city" ,0 ] }, as : "ct", in : { $filter : { input : "$$ct" , as : "ctyy", cond : { $eq : ["$$ctyy.key", "$city"] } } } } }, as : "o", cond : {$ne : [ {$size : "$$o"} , 0 ] } } } , 0]}, as : "o", in :"$$o.uuid"}}, 0]}
}
}
]
)
result
> db.u.aggregate( [ { $lookup: { from : "c", localField : "country", foreignField : "key", as : "countryInfo" } }, { $project: { "_id" : 1, "user" : 1, "province" : 1, "country" : 1, "city" : 1, "organization" : 1, "country_uuid" : {$arrayElemAt : ["$countryInfo.uuid",0]}, "province_uuid" : { $arrayElemAt : [{ $map : { input : { $filter : { input : {$arrayElemAt : ["$countryInfo.province" ,0 ]} , as : "pro", cond : { $eq : [ "$$pro.key", "$province" ] } } } , as : "pr", in : "$$pr.uuid" } }, 0 ] }, "city_uuid" : {$arrayElemAt : [{$map : { input : { $arrayElemAt : [ {$filter : { input : { $map : { input : { $arrayElemAt : ["$countryInfo.province.city" ,0 ] }, as : "ct", in : { $filter : { input : "$$ct" , as : "ctyy", cond : { $eq : ["$$ctyy.key", "$city"] } } } } }, as : "o", cond : {$ne : [ {$size : "$$o"} , 0 ] } } } , 0]}, as : "o", in :"$$o.uuid"}}, 0]} } } ] ).pretty()
{
"_id" : "549120bcf5115900124fb6e1",
"user" : "Tom",
"country" : "United Kingdom",
"province" : "North Yorkshire",
"city" : "York",
"organization" : "",
"country_uuid" : "d756e167-25ec-4aa9-b231-4dbf6d4bfce4",
"province_uuid" : "73d07c77-eba4-4dfa-9ada-e0ba8d8a2d55",
"city_uuid" : "80fd18a6-c4eb-4fb9-b591-6cca62319ba7"
}
Related
I am using mongoDB as backend server, I have nested array(one level array) like this
{
"_id" : ObjectId("60b1fc6d3c43f74e0c1dba92"),
"seriesId" : "60acebf73acb5b3a98d14331",
"name" : "Season 1",
"logoURL" : "uploads/season/1622277216401.png",
"yearOfPublish" : "2021-05-29",
"description" : "Season 1",
"createdBy" : ObjectId("609cbf49ba46cc3924859ab5"),
"createdOn" : "2021-05-29T08:33:49.480Z",
"episode" : [
{
"seasonId" : "60b1fc6d3c43f74e0c1dba92",
"name" : "Episode 1",
"id" : 0,
"logoURL" : "uploads/episode/1622278616899.png",
"dateOfTelecast" : null,
"description" : "sadfgh",
"duration" : "30",
"videoType" : "customURL",
"embedCode" : "",
"url" : "https://youtu.be/kbpsXMUr7ss",
"liveboxChannel" : "",
"createdOn" : "2021-05-29T08:56:59.230Z",
"createdBy" : ObjectId("609cbf49ba46cc3924859ab5"),
"_id" : "ZaVrpOLO5"
},
{
"seasonId" : "60b1fc6d3c43f74e0c1dba92",
"name" : "Episode 2",
"id" : 0,
"logoURL" : "uploads/episode/1622279206607.png",
"dateOfTelecast" : null,
"description" : "adfd",
"duration" : "30",
"videoType" : "customURL",
"embedCode" : "",
"url" : "https://youtu.be/kbpsXMUr7ss",
"liveboxChannel" : "",
"createdOn" : "2021-05-29T09:06:48.637Z",
"createdBy" : ObjectId("609cbf49ba46cc3924859ab5"),
"_id" : "9GKqXhxcH"
},}
I have more no of seasons. from the season collection,i have episode array under the name of Episode.
Now My frontend page required that episode array alone.
response = {episode: all the episode data} and this episode data is based on skip and limit value
I have tried something in mongodb,
db.getCollection('season_copy').aggregate([
{$project: {
episodes: {
$cond:{ if: { $isArray: "$episode" }, then: { input:"$episode" }, else: 0 }
},
},
},
])
Can anyone suggest me some idea?
Check this out:
Without aggregate:
db.getCollection('season_copy')
.find({ _id: ObjectID(id)})
.project({ episode: 1 }).toArray();
With aggregate:
MongoDB playground
db.getCollection('season_copy')
.aggregate([
{
$match: {
_id: ObjectId("60b1fc6d3c43f74e0c1dba92")
}
},
{
$project: {
episode: 1
}
}
])
I am trying to parse a JSON object and delete the Key 'id' with in it, I was able to delete the 'id' which appears in the root of the object but unable to traverse with in the nested array objects which also has 'id' key and delete them, Now follows the code block
var json = {
"id" : "a28b469b-b4f2-4846-9b5f-9d866f249bbe",
"description" : "Cost of Product",
"periodicity" : "calendar-monthly",
"Vanilla" : [ {
"id" : "22382c50-f56f-40b7-a308-203da052c5bc",
"price" : {
"amount" : 100.000,
"currency" : "USD"
},
"packing" : "RECURRING",
"billedInAdvance" : true
} ],
"Chocolate" : [ {
"id" : "44672921-1966-456e-bde2-87ef72f31cab",
"price" : {
"amount" : 256.000000,
"currency" : "USD"
},
"packing" : "Box_Usage"
} ],
"Peach" : [ {
"id" : "e3a600e2-a2ed-4872-8e6d-5d59ec5ca02d",
"packing" : "Box_Usage",
"diff" : [ {
"pricePerUnit" : {
"amount" : 25.000000,
"currency" : "USD"
},
"fixedPrice" : {
"amount" : 36.000000,
"currency" : "USD"
}
} ]
} ],
"Strawberry" : [ {
"id" : "43b4a121-455a-4828-b4bf-1bacda49f9ce",
"packing" : "Box_Usage",
"diff" : [ {
"pricePerUnit" : {
"amount" : 100.000000,
"currency" : "USD"
}
} ]
} ]
}
I am able to delete the 'id' property within an array object by accessing it through the index, But this wont handle dynamic scenarios when the keys with in the JSON grows. Any suggestion would be valuable
You can do it recursively: each time you find an array within the object, you loop through it to remove id in each element.
var json = {
"id" : "a28b469b-b4f2-4846-9b5f-9d866f249bbe",
"description" : "Cost of Product",
"periodicity" : "calendar-monthly",
"Vanilla" : [ {
"id" : "22382c50-f56f-40b7-a308-203da052c5bc",
"price" : {
"amount" : 100.000,
"currency" : "USD"
},
"packing" : "RECURRING",
"billedInAdvance" : true
} ],
"Chocolate" : [ {
"id" : "44672921-1966-456e-bde2-87ef72f31cab",
"price" : {
"amount" : 256.000000,
"currency" : "USD"
},
"packing" : "Box_Usage"
} ],
"Peach" : [ {
"id" : "e3a600e2-a2ed-4872-8e6d-5d59ec5ca02d",
"packing" : "Box_Usage",
"diff" : [ {
"pricePerUnit" : {
"amount" : 25.000000,
"currency" : "USD"
},
"fixedPrice" : {
"amount" : 36.000000,
"currency" : "USD"
}
} ]
} ],
"Strawberry" : [ {
"id" : "43b4a121-455a-4828-b4bf-1bacda49f9ce",
"packing" : "Box_Usage",
"diff" : [ {
"pricePerUnit" : {
"amount" : 100.000000,
"currency" : "USD"
}
} ]
} ]
};
function removeId(obj) {
delete obj.id;
Object.keys(obj).forEach(key => {
if (Array.isArray(obj[key])) {
obj[key].forEach(o => {
removeId(o);
});
}
});
}
removeId(json);
console.log(json);
My data is in the pattern -
{
"_id" : ObjectId("592ea5d8026c1e263c3d99d9"),
"projectName" : "Yosemite",
"events" : {
"eventName" : "Great",
"eventDate" : ISODate("2018-05-30T00:00:00.000+05:30")
}
},
{
"_id" : ObjectId("5954d98f7be20e32842aea16"),
"projectName" : "Alfa Beta",
"events" : {
"eventName" : "Final Review",
"eventDate" : ISODate("2017-07-31T00:00:00.000+05:30")
}
},
{
"_id" : ObjectId("5954dc0023aac8f9f28ec8d2"),
"projectName" : "Hackthon",
"events" : {
"eventName" : "2nd Review",
"eventDate" : ISODate("2017-07-23T00:00:00.000+05:30")
}
},
{
"_id" : ObjectId("5954dc0023aac8f9f28ec8d2"),
"projectName" : "Hackthon",
"events" : {
"eventName" : "Final Review",
"eventDate" : ISODate("2017-07-31T00:00:00.000+05:30")
}
}
I tried the following procedure available in [Group nested array in Javascript
]1
var Dataset1 = [{"commentBy":"saurabh","comment":"Testing","datestamp":"07/07/2017","weekcount":1},{"commentBy":"raman","comment":"Planning","datestamp":"07/07/2017","weekcount":1},{"commentBy":"Execution","comment":"Alfa Beta","datestamp":"07/07/2017","weekcount":2},{"commentBy":"Execution","comment":"Zseta Gama","datestamp":"07/07/2017","weekcount":2}];
var helperMap = {};
var result = Dataset1.reduce(function(arr, obj) {
var current = helperMap[obj.weekcount];
if(!current) {
current = {
weekcount: obj.weekcount,
grouped: []
};
helperMap[obj.weekcount] = current;
arr.push(current);
}
current.grouped.push({
commentBy: obj.commentBy,
comment: obj.comment,
datestamp: obj.datestamp
});
return arr;
}, []);
console.log(result);
However, my concern is not resolved.
I want my data to be appear in this way -
{
"_id" : ObjectId("592ea5d8026c1e263c3d99d9"),
"projectName" : "Yosemite",
"events" : {
"eventName" : "Great",
"eventDate" : ISODate("2018-05-30T00:00:00.000+05:30")
}
},
{
"_id" : ObjectId("5954d98f7be20e32842aea16"),
"projectName" : "Alfa Beta",
"events" : {
"eventName" : "Final Review",
"eventDate" : ISODate("2017-07-31T00:00:00.000+05:30")
}
},
{
"_id" : ObjectId("5954dc0023aac8f9f28ec8d2"),
"projectName" : "Hackthon",
"events" : {
"eventName" : "2nd Review",
"eventDate" : ISODate("2017-07-23T00:00:00.000+05:30")
},
{
"eventName" : "Final Review",
"eventDate" : ISODate("2017-07-31T00:00:00.000+05:30")
}
}
So that the _id or projectName should not repeat.
Please help me.
Need help on operation like update,delete,add,upsert,delete on below document of MongoDB.
Below is MongoDB document that exists in temp collection.
{
"local_id" : "1841",
"name_first" : "tiger",
"name_last" : "lion",
"address" : [
{
"id" : 1,
"address_type" : "Home",
"city" : "Delhi",
"country" : "",
"po_box" : ""
},
{
"id" : 2,
"address_type" : "Work",
"city" : "",
"country" : "",
"po_box" : ""
}
],
"email" : [
{
"email_id" : "blah#gmail.com",
"id" : 1,
"type" : "Home"
},
{
"email_id" : "Pearl1#gmail.com",
"id" : 2,
"type" : "Work"
}
],
"phone_number" : [
{
"id" : 1,
"no" : "+911234567890",
"type" : "Mobile"
},
{
"id" : 2,
"no" : "+917894561230",
"type" : "work"
}
]
}`
Now I have some document like below, i want query that will compare,add,update,delete on my above document.
`
{
"local_id" : "1730",
"name_first" : "lion",
"name_last" : "king",
"address" : [
{
"id" : 1,
"address_type" : "Home",
"city" : "Delhi",
"country" : "India",
"po_box" : "110041"
},
{
"id" : 2,
"address_type" : "Work",
"city" : "Delhi-NCR",
"country" : "India",
"po_box" : "110048"
},
{
"id" : 3,
"address_type" : "Work",
"city" : "Delhi-NCR",
"country" : "Indai",
"po_box" : "110048"
}
],
"email" : [
{
"email_id" : "updatethis#gmail.com",
"id" : 1,
"type" : "Home"
},
{
"email_id" : "Pearl1#gmail.com",
"id" : 2,
"type" : "Work"
},
{
"email_id" : "addthisarray#gmail.com",
"id" : 3,
"type" : "personal"
}
],
"phone_number" : [
{
"id" : 1,
"no" : "+911234567890",
"type" : "Mobile"
}
/*second array not here so remove that array from that document*/
]
}`
You can save function on server as you can call that function to get the differences, as below.
db.system.js.save({
_id: "getupdatedArray",
value: function(obj1, obj2) {
var VALUE_CREATED = 'created';
var VALUE_UPDATED = 'updated';
var VALUE_DELETED = 'deleted';
var VALUE_UNCHANGED = 'unchanged';
function map(obj1, obj2) {
if (isValue(obj1) || isValue(obj2)) {
return {
type: compareValues(obj1, obj2),
old: obj1,
new: obj2
};
}
var diff = {};
for (var key in obj1) {
if (isFunction(obj1[key])) {
continue;
}
var value2 = undefined;
if ('undefined' != typeof(obj2[key])) {
value2 = obj2[key];
}
diff[key] = map(obj1[key], value2);
}
for (var key in obj2) {
if (isFunction(obj2[key]) || ('undefined' != typeof(diff[key]))) {
continue;
}
diff[key] = map(undefined, obj2[key]);
}
return diff;
}
function compareValues(value1, value2) {
if (value1 === value2) {
return VALUE_UNCHANGED;
}
if ('undefined' == typeof(value1)) {
return VALUE_CREATED;
}
if ('undefined' == typeof(value2)) {
return VALUE_DELETED;
}
return VALUE_UPDATED;
}
function isFunction(obj) {
return {}.toString.apply(obj) === '[object Function]';
}
function isArray(obj) {
return {}.toString.apply(obj) === '[object Array]';
}
function isObject(obj) {
return {}.toString.apply(obj) === '[object Object]';
}
function isValue(obj) {
return !isObject(obj) && !isArray(obj);
}
return map(obj1, obj2);
}
})
Then you can call function as below..
db.loadServerScripts();
getupdatedArray({"a": "abc"}, {"a": "a111", "b": "bbb"});
This will give you result as below:
{
"a" : {
"type" : "updated",
"old" : "abc",
"new" : "a111"
},
"b" : {
"type" : "created",
"old" : undefined,
"new" : "bbb"
}
}
Thanks
Satish Lakhani
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
}