Reputation: 6403
I would like to query a subdocument where results must have all fields specified and no others. Is this possible? And if so how?
For example:
I want a query like this:
db.users.find({
"pref.no_popup": true,
"pref.font_large": false,
"pref": { "$size", 2 }});
To match this:
{
"user": "Ed",
"pref": {
"no_popup": true,
"font_large": false
}
}
But not this:
{
"user": "James",
"pref": {
"no_popup": true,
"font_large": false,
"font_red": true
}
}
I realise the $size operator is designed for arrays, so how can I do something similar for subdocuments?
Note that I did try not using a dot notation to query for exact field presence but then I had issues with ordering.
Upvotes: 3
Views: 150
Reputation: 1085
I think you're going to have to use a mapReduce...
Not ideal, but should solve the problem.
mapper=function(){ for (key in this.pref){
emit(this._id, {'count':1}); \\assume your user id is called _id
}
}
reducer=function(k,v){
counter=0;
for (i=0;i<v.length;i++){
counter+=v[i].count;
}
return {'count':counter}
}
This should give you a collection with people's IDs and the number of prefs that have been set
Upvotes: 0
Reputation: 1851
If your have many properties that you do not wont to match, and only two that wont, you could try something like this to solve order problem (as upgrade to Andrei answer):
db.users.find({ $or: [
"pref" : {
"no_popup" : true,
"font_large" : false
},
"pref" : {
"font_large" : false,
"no_popup" : true
} ] });
Upvotes: 1
Reputation: 851
Have you checked $exists operator?
db.users.find({
"pref.font_red" : {"$exists":false}
});
Upvotes: 1
Reputation: 4623
There is this "Exact match on subdocument" scenario. Here, search in page for the quoted text.
I think that your query should be:
db.users.find({
"pref" : {
"no_popup" : true,
"font_large" : false
} });
Upvotes: 1