mongodb $in, search deeply nested subdocument - mongodb

I have the following collections in mongo:
> db.styles.find({ "_id" : "EP01L"}).pretty();
{
"_id" : "EP01L",
"__v" : 5,
"categoryIds" : [
ObjectId("5550dcc7a14c976741483c89"),
ObjectId("5550dcc7a14c976741483c8d")
],
"collectionId" : ObjectId("5550dab4a14c9766418ff2af"),
"colours" : {
"WH" : [
{
"on_sale" : false,
"size_code_id" : "S",
"sku" : "EP01L-WH1"
},
],
"BL" : [
{
"on_sale" : false,
"size_code_id" : "S",
"sku" : "EP01L-BL1"
},
]
},
"fabric" : {
"material" : [
{
"_id" : ObjectId("5550dab4a14c9766418ff2c4"),
"value" : 100
}
],
"type" : ObjectId("5550dab4a14c9766418ff2d1"),
"weight" : {
"ounce" : {
"min" : 4
},
"gram" : {
"min" : 155
}
}
},
"name" : {
"es-ES" : "CAMISETA MANGA LARGA HOMBRE",
"it-IT" : "T-SHIRT UOMO MANICA LUNGA",
"en-UK" : "MEN’S LONG SLEEVE T-SHIRT",
"fr-FR" : "T-SHIRT HOMME MANCHES LONGUES"
},
}
and
> db.attributes.find({"name.en-UK": "Fabric"}).pretty();
{
"_id" : ObjectId("5550dab4a14c9766418ff2dc"),
"values" : {
"source" : [
{
"code" : 1,
"_id" : ObjectId("5550dab4a14c9766418ff2bf"),
"name" : {
"fr-FR" : "Coton",
"it-IT" : "Cotone",
"en-UK" : "Cotton",
"es-ES" : "Algodón"
}
},
{
"code" : 2,
"_id" : ObjectId("5550dab4a14c9766418ff2c0"),
"name" : {
"fr-FR" : "Viscose",
"it-IT" : "Viscosa",
"en-UK" : "Viscose",
"es-ES" : "Viscosa"
}
},
],
"name" : [
{
"_id" : ObjectId("5550dab4a14c9766418ff2cd"),
"name" : {
"en-UK" : "3-ply Loopback"
}
},
{
"_id" : ObjectId("5550dab4a14c9766418ff2db"),
"name" : {
"en-UK" : "Woven Twill"
}
}
]
},
"name" : {
"en-UK" : "Fabric"
}
}
I am trying to write a query to find all the style documents that where fabric.source is either Cotton or Viscose and fabric.name is Woven Twill.
this query gives me all the documents that have fabric.type are Cotton or Viscose
> db.styles.find( { "fabric.type": { $in: [ ObjectId("5550dab4a14c9766418ff2cd"), ObjectId("5550dab4a14c9766418ff2db") ] } } ).count();
3
>
but how do I find all the styles where the size_code_id is S and colours is WH?

Please check the below query :
db.styles.find({
$and:[
{ "colours.WH" :{ $exists:1 } } ,
{ "colours.WH.size_code_id" : "S"}
]
}
).pretty();
If you need to find for "WH" and "BL", you can query like below :
db.styles.find({
$or:[
{
$and:[
{ "colours.WH" :{ $exists:1 } } ,
{ "colours.WH.size_code_id" : "S"}
]
},
{
$and:[
{ "colours.BL" :{ $exists:1 } } ,
{ "colours.BL.size_code_id" : "S"}
]
}
]
}
).pretty();
P.S : If you need to query for the multiple colors say for some 5- 10 different colours, Then you should construct the query dynamically for all those colors using JavaScript language constructs.
Below is the TESTED code for constructing the query dynamically :
// Colours you want to search
var varray = new Array("WH","BL");
var fname = "colours", lname = "size_code_id";
var arr = new Array();
var mquery = {"$or":[]};
for( var i = 0; i < varray.length; i++ )
{
var query = { "$and" : []};
// This line will dynamically construct a key as "colours.WH"
var s1 = fname.concat(".").concat(varray[i]);
// This line will dynamically construct a key as "colours.WH.size_code_id"
var s2 = fname.concat(".").concat(varray[i]).concat(".").concat(lname);
var sub1 = {}, sub2 = {};
sub1[s1] = { $exists:1 };
sub2[s2] = "S";
query["$and"].push(sub1);
query["$and"].push(sub2);
arr.push(query);
}
mquery["$or"] =arr;
db.styles.find(mquery);

Related

Return specific array value field in aggregate

I have a issue in MongoDB i'm trying to build a very complex aggregate query, and its work almost as i want it, but i still have trobles, and the problems is i need to move a spefiect field so i can use it later.
My aggregate look like this right now.
db.getCollection('travel_sights').aggregate([{
'$match': {
'preview.photo' : {
'$exists':true
},
'_id': {
'$in' : [ObjectId("5b7af9701fbad410e10f32f7")]
}
}
},{
'$unwind' : '$preview.photo'
}, {
'$lookup':{
'from' : 'media_data',
'localField' : '_id',
'foreignField':'bind',
'as':'media'
}
}])
and it will return data like this.
{
"_id" : ObjectId("5b7af9701fbad410e10f32f7"),
"preview" : {
"photo" : {
"id" : ObjectId("5b7affea1fbad441494a663b"),
"sort" : 0
}
},
"media" : [
{
"_id" : ObjectId("5b7affea1fbad441494a663b")
},
{
"_id" : ObjectId("5b7b002d1fbad441494a663c")
},
{
"_id" : ObjectId("5b7b00351fbad441494a663d")
},
{
"_id" : ObjectId("5b7d9baa1fbad410de638bbb")
},
{
"_id" : ObjectId("5b7d9bae1fbad410e10f32f9")
},
{
"_id" : ObjectId("5b7d9bb11fbad441494a663e")
},
{
"_id" : ObjectId("5b7d9bb41fbad4ff97273402")
},
{
"_id" : ObjectId("5b7d9bb71fbad4ff99527e82")
},
{
"_id" : ObjectId("5b7d9bbb1fbad410de638bbc")
},
{
"_id" : ObjectId("5b7d9bbe1fbad410e10f32fa")
},
{
"_id" : ObjectId("5b7d9bc11fbad441494a663f")
},
{
"_id" : ObjectId("5b7d9bc41fbad4ff97273403")
},
{
"_id" : ObjectId("5b7d9bc71fbad4ff99527e83")
},
{
"_id" : ObjectId("5b7d9bca1fbad410de638bbd")
},
{
"_id" : ObjectId("5b7d9bcd1fbad441494a6640")
},
{
"_id" : ObjectId("5b7d9bd01fbad4ff97273404")
}
]
}
{
"_id" : ObjectId("5b7af9701fbad410e10f32f7"),
"preview" : {
"photo" : {
"id" : ObjectId("5b7b002d1fbad441494a663c"),
"sort" : 0
}
},
"media" : [
{
"_id" : ObjectId("5b7affea1fbad441494a663b")
},
{
"_id" : ObjectId("5b7b002d1fbad441494a663c")
},
{
"_id" : ObjectId("5b7b00351fbad441494a663d")
},
{
"_id" : ObjectId("5b7d9baa1fbad410de638bbb")
},
{
"_id" : ObjectId("5b7d9bae1fbad410e10f32f9")
},
{
"_id" : ObjectId("5b7d9bb11fbad441494a663e")
},
{
"_id" : ObjectId("5b7d9bb41fbad4ff97273402")
},
{
"_id" : ObjectId("5b7d9bb71fbad4ff99527e82")
},
{
"_id" : ObjectId("5b7d9bbb1fbad410de638bbc")
},
{
"_id" : ObjectId("5b7d9bbe1fbad410e10f32fa")
},
{
"_id" : ObjectId("5b7d9bc11fbad441494a663f")
},
{
"_id" : ObjectId("5b7d9bc41fbad4ff97273403")
},
{
"_id" : ObjectId("5b7d9bc71fbad4ff99527e83")
},
{
"_id" : ObjectId("5b7d9bca1fbad410de638bbd")
},
{
"_id" : ObjectId("5b7d9bcd1fbad441494a6640")
},
{
"_id" : ObjectId("5b7d9bd01fbad4ff97273404")
}
]
}
{
"_id" : ObjectId("5b7af9701fbad410e10f32f7"),
"preview" : {
"photo" : {
"id" : ObjectId("5b7b00351fbad441494a663d"),
"sort" : 0,
"primary" : false
}
},
"media" : [
{
"_id" : ObjectId("5b7affea1fbad441494a663b")
},
{
"_id" : ObjectId("5b7b002d1fbad441494a663c")
},
{
"_id" : ObjectId("5b7b00351fbad441494a663d")
},
{
"_id" : ObjectId("5b7d9baa1fbad410de638bbb")
},
{
"_id" : ObjectId("5b7d9bae1fbad410e10f32f9")
},
{
"_id" : ObjectId("5b7d9bb11fbad441494a663e")
},
{
"_id" : ObjectId("5b7d9bb41fbad4ff97273402")
},
{
"_id" : ObjectId("5b7d9bb71fbad4ff99527e82")
},
{
"_id" : ObjectId("5b7d9bbb1fbad410de638bbc")
},
{
"_id" : ObjectId("5b7d9bbe1fbad410e10f32fa")
},
{
"_id" : ObjectId("5b7d9bc11fbad441494a663f")
},
{
"_id" : ObjectId("5b7d9bc41fbad4ff97273403")
},
{
"_id" : ObjectId("5b7d9bc71fbad4ff99527e83")
},
{
"_id" : ObjectId("5b7d9bca1fbad410de638bbd")
},
{
"_id" : ObjectId("5b7d9bcd1fbad441494a6640")
},
{
"_id" : ObjectId("5b7d9bd01fbad4ff97273404")
}
]
}
and what you can se the last data have preview.photo.primary on it, and this field i want to return when i'm done with my aggregate query.
My final query look like this:
db.getCollection('travel_sights').aggregate([{
'$match': {
'preview.photo' : {
'$exists':true
},
'_id': {
'$in' : [ObjectId("5b7af9701fbad410e10f32f7")]
}
}
},{
'$unwind' : '$preview.photo'
}, {
'$lookup':{
'from' : 'media_data',
'localField' : '_id',
'foreignField':'bind',
'as':'media'
}
},{
'$unwind':'$media'
},{
'$project' : {
'preview' : 1,
'media': 1,
}
}, {
'$group': {
'_id':'$media._id',
'primary': {
'$first':'$preview'
}
}
}])
The problem here is when i want $preview return so i can find the primary about it, its allways only return the first where the value not exists, if i use $push the problem is i get every thing.
is there a way so i can pick the right primary value in my return? have trying $addFields to but whitout eny kind of lock.
Travel_sights data:
{
"_id" : ObjectId("5b7af9701fbad410e10f32f7"),
"city_id" : ObjectId("5b6d0cb6222d4c70b803eaeb"),
"activated" : true,
"deleted" : false,
"url" : "url is here",
"name" : "title of it here",
"updated_at" : ISODate("2018-08-22T17:22:27.000Z"),
"content" : "content here",
"preview" : {
"photo" : [
{
"id" : ObjectId("5b7affea1fbad441494a663b"),
"sort" : 0
},
{
"id" : ObjectId("5b7b002d1fbad441494a663c"),
"sort" : 0
},
{
"id" : ObjectId("5b7b00351fbad441494a663d"),
"sort" : 0,
"primary" : true
},
{
"id" : ObjectId("5b7d9baa1fbad410de638bbb"),
"sort" : 0
},
{
"id" : ObjectId("5b7d9bae1fbad410e10f32f9"),
"sort" : 0
},
{
"id" : ObjectId("5b7d9bb11fbad441494a663e"),
"sort" : 0
},
{
"id" : ObjectId("5b7d9bb41fbad4ff97273402"),
"sort" : 0,
"primary" : false
},
{
"id" : ObjectId("5b7d9bb71fbad4ff99527e82"),
"sort" : 0,
"primary" : false
},
{
"id" : ObjectId("5b7d9bbb1fbad410de638bbc"),
"sort" : 0
},
{
"id" : ObjectId("5b7d9bbe1fbad410e10f32fa"),
"sort" : 0
},
{
"id" : ObjectId("5b7d9bc11fbad441494a663f"),
"sort" : 0
},
{
"id" : ObjectId("5b7d9bc41fbad4ff97273403"),
"sort" : 0,
"primary" : false
},
{
"id" : ObjectId("5b7d9bc71fbad4ff99527e83"),
"sort" : 0,
"primary" : false
},
{
"id" : ObjectId("5b7d9bca1fbad410de638bbd"),
"sort" : 0,
"primary" : false
},
{
"id" : ObjectId("5b7d9bcd1fbad441494a6640"),
"sort" : 0,
"primary" : false
},
{
"id" : ObjectId("5b7d9bd01fbad4ff97273404"),
"sort" : 0
}
]
}
}
3 sample foto bind data here:
{
"_id" : ObjectId("5b7affea1fbad441494a663b"),
"file-name" : "55575110311__0F115282-B5A0-4654-AA44-B7DC2C682992.jpeg",
"options" : [
ObjectId("5b6fb855222d4c70b8041093")
],
"type" : "images",
"files" : [
{
"width" : 70,
"height" : 53
},
{
"width" : 400,
"height" : 300
},
{
"width" : 800,
"height" : 600
},
{
"width" : 1600,
"height" : 1200
}
],
"bind" : [
ObjectId("5b7af9701fbad410e10f32f7")
]
}
{
"_id" : ObjectId("5b7b002d1fbad441494a663c"),
"file-name" : "55575110748__E7B07EFD-9F7E-40D6-8B57-38F708E4C0C0.jpeg",
"options" : [
ObjectId("5b6fb855222d4c70b8041093")
],
"type" : "images",
"files" : [
{
"width" : 70,
"height" : 53
},
{
"width" : 400,
"height" : 300
},
{
"width" : 800,
"height" : 600
},
{
"width" : 1600,
"height" : 1200
}
],
"bind" : [
ObjectId("5b7af9701fbad410e10f32f7")
],
"description" : "this is secoudn demo!",
"title" : "demo 3"
}
{
"_id" : ObjectId("5b7b00351fbad441494a663d"),
"file-name" : "paris2.jpg",
"options" : [
ObjectId("5b6fb855222d4c70b8041093")
],
"type" : "images",
"files" : [
{
"width" : 70,
"height" : 53
},
{
"width" : 400,
"height" : 300
},
{
"width" : 800,
"height" : 600
},
{
"width" : 1600,
"height" : 1200
}
],
"bind" : [
ObjectId("5b7af9701fbad410e10f32f7")
],
"description" : "this is a demo1 :)",
"title" : "demo"
}
You can filter out the element from the array where the primary field exists using $filter aggregation and then easily $group with the media._id field and get the $first document value.
Finally your query will be
db.getCollection("travel_sights").aggregate([
{ "$match": {
"preview.photo" : { "$exists":true },
"_id": { "$in" : [ ObjectId("5b7af9701fbad410e10f32f7") ] }
}},
{ "$addFields": {
"preview.photo": {
"$arrayElemAt": [
{ "$filter": {
"input": "$preview.photo",
"as": "photo",
"cond": { "$ne": [ "$$photo.primary", undefined ] }
}}, 0
]
}
}},
{ "$lookup":{
"from" : "media_data",
"localField" : "_id",
"foreignField": "bind",
"as": "media"
}},
{ "$unwind":"$media" },
{ "$project" : { "preview" : 1, "media": 1, }},
{ "$group": {
"_id": "$media._id",
"primary": { "$first": "$preview" }
}}
])

need to filter query to get selected object in mongodb

I have the below document.
I want to return "employeedata" containing only those array objects (family, academic etc.) for which status is "current"
{
"_id" : ObjectId("5a1fe7ed1e9fdd17285ac13f"),
"createdby" : "admin",
"details" : [
{
"_id" : ObjectId("5a1fe81f1e9fdd17285ac14a"),
"employeedata" : {
"createddate" : "2017-11-30T11:13:57.290Z",
"family" : [
{
"status" : "current",
"_id" : ObjectId("5a1fe81f1e9fdd17285ac153")
}
],
"academic" : [
{
"status" : "archive",
"_id" : ObjectId("5a1fe81f1e9fdd17285ac159")
},
{
"status" : "current",
"_id" : ObjectId("5a1fe8a71e9fdd17285ac15d")
}
],
"company" : [
{
"status" : "archive",
"_id" : ObjectId("5a1fe81f1e9fdd17285ac150")
},
{
"status" : "current",
"_id" : ObjectId("5a1fe88e1e9fdd17285ac15c")
}
],
"other" : [
{
"status" : "current",
"_id" : ObjectId("5a1fe81f1e9fdd17285ac154")
}
]
}
}
]
"confirmed" : true,
}
You can try following to filter the object as it is an complex object we will have to loop through the complete object and modify it at run time.
var data = JSON.parse('{"_id":"5a1fe7ed1e9fdd17285ac13f","createdby":"admin","details":[{"_id":"5a1fe81f1e9fdd17285ac14a","employeedata":{"createddate":"2017-11-30T11:13:57.290Z","family":[{"status":"current","_id":"5a1fe81f1e9fdd17285ac153"}],"academic":[{"status":"archive","_id":"5a1fe81f1e9fdd17285ac159"},{"status":"current","_id":"5a1fe8a71e9fdd17285ac15d"}],"company":[{"status":"archive","_id":"5a1fe81f1e9fdd17285ac150"},{"status":"current","_id":"5a1fe88e1e9fdd17285ac15c"}],"other":[{"status":"current","_id":"5a1fe81f1e9fdd17285ac154"}]}}]}');
function createObject() {
for (var obj in data.details[0].employeedata) {
if (Array.isArray(data.details[0].employeedata[obj])) {
data.details[0].employeedata[obj].filter(function (value, index) {
if (value.status !== 'current') {
//return value;
data.details[0].employeedata[obj].splice(index, 1);
}
})
}
}
}

MongoDB 3.2 Update Field name in embedded array

Im trying to do a i migration in my MongoDB. I have updated a Field from Content -> StringContent. Now I want to update all records that exists with the new Field name.
This is how a document looks like.
{
"_id" : "c4af0b19-4c78-4e58-bbe5-ac9e5cce2c3f",
"Type" : "Onboarding",
"Cards" : [
{
"_id" : LUUID("3f328a1c-658d-ee4e-8f06-561760eb5be5"),
"Width" : 1,
"Title" : "",
"Type" : "Freetext",
"Description" : "",
"Content" : "This is a test" // -> "StringContent" : "This is a Test"
},
{
"_id" : LUUID("2f328a1c-658d-ee4e-8f06-561760eb5be5"),
"Width" : 1,
"Title" : "",
"Type" : "Freetext",
"Description" : "",
"Content" : "This is another test" //-> "StringContent" : "This is another Test"
}
],
"DocumentType" : "Template",
"History" : [
{
"Date" : ISODate("2017-07-13T12:03:01.620Z"),
"ByUserId" : LUUID("4ecaa6ca-2ce6-f84c-81f3-28f8f0256e6e")
}
],
"Name" : "Default Template"
}
I have created this script:
var bulk = db.getCollection('OnboardingPortal').initializeOrderedBulkOp(),
count = 0;
db.getCollection('OnboardingPortal').find({"DocumentType": "Template"}).
forEach(function(doc) {
doc.Cards.forEach(function(card) {
if(card.hasOwnProperty("Content")){
print(card);
bulk.find({"_id": doc._id, "Cards._id": card._id}).update(
{
$set: {"Cards.$.StringContent": card.Content}
});
bulk.find({"_id": doc._id, "Cards._id": card._id}).update(
{
$unset: {"Cards.$.Content": 1}
});
count += 2;
if(count % 500 == 0) {
bulk.execute();
bulk = db.getCollection('OnboardingPortal').initializeOrderedBulkOp();
}
}
});
});
if ( count % 500 !== 0 ){
bulk.execute();
}
This Does not update anything, but if I change bulk.operations -> to explicit set index on array like this, it will do the job. but only for one card :
bulk.find({"_id": doc._id, "Cards.1._id": card._id}).update(
{
$set: {"Cards.1.StringContent": card.Content}
});
bulk.find({"_id": doc._id, "Cards.1._id": card._id}).update(
{
$unset: {"Cards.1.Content": 1}
});
What am i missing in my script so this can iterates over several documents and change Content-> StringContent in each Card. ?
EDIT
I have added a bulk.getOperations(); in my script. this is what it returns. Should it not have replaced $ with index ?
/* 1 */
[
{
"originalZeroIndex" : 0.0,
"batchType" : 2.0,
"operations" : [
{
"q" : {
"_id" : "c4af0b19-4c78-4e58-bbe5-ac9e5cce2c3f",
"Cards._id" : "1c8a323f-8d65-4eee-8f06-561760eb5be5"
},
"u" : {
"$set" : {
"Cards.$.StringContent" : "This is a cool test"
}
},
"multi" : false,
"upsert" : false
},
{
"q" : {
"_id" : "c4af0b19-4c78-4e58-bbe5-ac9e5cce2c3f",
"Cards._id" : "1c8a323f-8d65-4eee-8f06-561760eb5be5"
},
"u" : {
"$unset" : {
"Cards.$.Content" : 1.0
}
},
"multi" : false,
"upsert" : false
},
{
"q" : {
"_id" : "c4af0b19-4c78-4e58-bbe5-ac9e5cce2c3f",
"Cards._id" : "1c8a322f-8d65-4eee-8f06-561760eb5be5"
},
"u" : {
"$set" : {
"Cards.$.StringContent" : "This is a test"
}
},
"multi" : false,
"upsert" : false
},
{
"q" : {
"_id" : "c4af0b19-4c78-4e58-bbe5-ac9e5cce2c3f",
"Cards._id" : "1c8a322f-8d65-4eee-8f06-561760eb5be5"
},
"u" : {
"$unset" : {
"Cards.$.Content" : 1.0
}
},
"multi" : false,
"upsert" : false
}
]
}
]

How to return all project employees?

I have datas of following format collection(projects) inside my database:
{ "_id" : ObjectId("5981a80f223e491a58230e5d"), "id" : 2, "name" : "gbqplhlqxzwl", "managerId" : 65151, "startDate" : "03.11.1999", "finishDate" : "02.01.2003", "projectStatus" : "POSTPONED", "participants" : [ ], "estimatedBudget" : 6017891.811079914 }
{ "_id" : ObjectId("5981a80f223e491a58230e5e"), "id" : 3, "name" : "erfekfsdgryu", "managerId" : 83749, "startDate" : "07.07.2007", "finishDate" : "26.12.2027", "projectStatus" : "POSTPONED", "participants" : [ 19229, 81856, 79270, 5509, 70344, 39424 ], "estimatedBudget" : 3086213.8981674756 }
{ "_id" : ObjectId("5981a80f223e491a58230e5f"), "id" : 1, "name" : "jvbzobhppntd", "managerId" : 18925, "startDate" : "29.04.1999", "finishDate" : "13.10.2008", "projectStatus" : "OPEN", "participants" : [ 46100, 96968, 6676, 56121, 4716, 68901, 43990, 48587, 62547, 30292, 65153, 17551, 27083, 20261, 27097, 50036, 86585, 69890, 18790, 22592, 60774, 93709, 78471, 27157, 4328, 36501, 47296, 16831 ], "estimatedBudget" : 3581496.7068344904 }
{ "_id" : ObjectId("5981a80f223e491a58230e60"), "id" : 4, "name" : "cdspkkqwvwld", "managerId" : 62042, "startDate" : "13.03.1998", "finishDate" : "20.06.2007", "projectStatus" : "OPEN", "participants" : [ 53480, 60897, 23677, 22064, 60807, 66637, 84609, 28378, 87143, 27675, 79283, 94992, 20429, 48769, 91671, 41747, 21651, 91134, 41684, 57228, 51949, 18756, 45679, 87781, 67287, 6902, 27526 ], "estimatedBudget" : 2126283.953787842 }
....
I need to find the busiest employee and list all his projects.
participants array contains employee ids who participate in the project.
I use the following query to find the busiest employee:
db.projects.aggregate(
{
$unwind: '$participants'
},
{
$addFields: {
count: 1
}
},
{
$group: {
_id : '$participants',
participation_count : {
'$sum':'$count'
}
}
},
{
$sort:{participation_count:-1}
},
{
$limit:1
}
)
and this work correctly. But I have no ideas how to list all his projects.
any ideas?
db.projects.aggregate(
[
{
$unwind: '$participants'
},
{
$addFields: {
count: 1
}
},
{
$group: {
_id : '$participants',
participation_count : {'$sum':'$count'},
projectId : {$push: '$id'}
}
},
{
$sort:{participation_count:-1}
},
{
$limit:1
}
],
{
allowDiskUse:true
}
)

How to sort nested object

db.sort.drop();
db.sort.insert({stats: [{userId: 1, date: '01012013'},{userId: 2, date: '31122012'}]});
db.sort.insert({stats: [{userId: 1, date: '31122013'},{userId: 2, date: '01012012'}]});
> db.sort.find({'stats.userId': 1}).sort({'stats.date': 1}).pretty()
{
"_id" : ObjectId("52af1ce974be7dbd071e8563"),
"stats" : [
{
"userId" : 1,
"date" : "31122013"
},
{
"userId" : 2,
"date" : "01012012"
}
]
}
{
"_id" : ObjectId("52af1ce974be7dbd071e8562"),
"stats" : [
{
"userId" : 1,
"date" : "01012013"
},
{
"userId" : 2,
"date" : "31122012"
}
]
}
How to get the documents sorted by date userId: 1?
I expect to see:
{
"_id" : ObjectId("52af1ce974be7dbd071e8562"),
"stats" : [
{
"userId" : 1,
"date" : "01012013"
},
{
"userId" : 2,
"date" : "31122012"
}
]
}
{
"_id" : ObjectId("52af1ce974be7dbd071e8563"),
"stats" : [
{
"userId" : 1,
"date" : "31122013"
},
{
"userId" : 2,
"date" : "01012012"
}
]
}
Something along the lines of:
db.COLLECTION.find({stats.userID: 1}).sort({'stats.date':1})
Given your data above, when I execute that query, I get this back:
"stats" : [
{
"userId" : 1,
"date" : 1012013
}
You could use the aggregation framework to achieve
db.sort.aggregate(
[
{$unwind:"$stats"},
{$match:{"stats.userId":1}},
{$sort:{"stats.date":1}}
]);
If you could change your schema to store the user+id combination as the field name with the date as its value then you accomplish this easily
> db.so2.find().pretty()
{
"_id" : 1,
"stats" : [
{
"userId1" : "01012013"
},
{
"userId2" : "31122012"
}
]
}
{
"_id" : 2,
"stats" : [
{
"userId1" : "31122013"
},
{
"userId2" : "01012012"
}
]
}
You then change the query predicate from userId : 1 to check for existence of the userId field
> db.so2.find({"stats.userId1":{$exists:1}}).sort({"stats.userId1":1}).pretty()
{
"_id" : 1,
"stats" : [
{
"userId1" : "01012013"
},
{
"userId2" : "31122012"
}
]
}
{
"_id" : 2,
"stats" : [
{
"userId1" : "31122013"
},
{
"userId2" : "01012012"
}
]
}