Reputation: 7146
I have a collection with documents like the following:
{
"_id" : ObjectId("..."),
"some_key" : "some_value",
...,
"another_key" : {
"a key" : "a value",
...
}
}
There are a couple different types of documents that go into this collection, with the biggest differences happening in the "another_key" field.
I would like to be able to find documents based on the size of the subdocument in "another_key". If it were an array, I could use this query:
{
"another_key" : {
$size : 0
}
}
to find all documents for which it has been left empty. Unfortunately, as per the documentation this only works for arrays.
Is there a way to do this for subdocuments?
Upvotes: 3
Views: 4713
Reputation: 61235
Using Object.keys
to get the sub-documents keys and the $where
operator.
db.collection.find( {
'timestamp': "your value",
'$where': function() { return Object.keys(this.another_key).length === 0; }
})
Upvotes: 1
Reputation: 2972
Nested objects aren't really subdocuments, and I don't refer to them as subdocuments, since they don't act like a document, and can't use $
operators on them. Also indexing doesn't really work on them, however we can index 'another_key.key' for better search performance.
I would suggest turn another_key
into an array of objects(subdocuments) that looks like:
db.items.insert({
some_key : 'some_value',
another_key : [
{key: 'akey', value: 'avalue'},
{key: 'bkey', value: 'bvalue'}
]
});
You can now find by $size, and key if you want.
mongos> db.items.find({another_key: {$size: 0}})
// 0 documents
mongos> db.items.find({another_key: {$size: 1}})
// 0 documents
mongos> db.items.find({another_key: {$size: 2}})
{ "_id" : ObjectId("54f62a48e2fdcc95d4934424"), "some_key" : "some_value", "another_key" : [ { "key" : "akey", "value" : "avalue" }, { "key" : "bkey", "value" : "bvalue" } ] }
mongos> db.items.find({another_key: {$size: 3}})
// 0 documents
mongos> db.collection.find({'another_key.key': 'akey'})
{ "_id" : ObjectId("54f62a48e2fdcc95d4934424"), "some_key" : "some_value", "another_key" : [ { "key" : "akey", "value" : "avalue" }, { "key" : "bkey", "value" : "bvalue" } ] }
Unfortunately you can't do comparitive $size
queries:
mongos> db.items.find({another_key: {$size: {$gt:1} } } )
error: {
"$err" : "Can't canonicalize query: BadValue $size needs a number",
"code" : 17287
}
Upvotes: 1