I'm trying to find all documents that do not contain at least one document with a specific field value. For example here is a sample collection:
{ _id : 1, docs : [ { foo : 1, bar : 2}, { foo : 3, bar : 3} ] }, { _id : 2, docs : [ { foo : 2, bar : 2}, { foo : 3, bar : 3} ] }
I want to find every record where there is not a document in the docs block that does not contain at least one record with foo = 1. In the example above, only the second document should be returned.
I have tried the following, but it only tells me if there are any that don't match (which returns document 1.
db.collection.find({"docs": { $not: {$elemMatch: {foo: 1 } } } })
UPDATE: The query above actually does work. As many times happens, my data was wrong, not my code.
I have also looked at the $nin operator but the examples only show when the array contains a list of primitive values, not an additional document. When I've tried to do this with something like the following, it looks for the EXACT document rather than just the foo field I want.
db.collection.find({"docs": { $nin: {'foo':1 } } })
Is there anyway to accomplish this with the basic operators?
To search the array of object in MongoDB, you can use $elemMatch operator. This operator allows us to search for more than one component from an array object.
You can query for multiple documents in a collection with collection. find() . The find() method uses a query document that you provide to match the subset of the documents in the collection that match the query.
Find() Method. In MongoDB, find() method is used to select documents in a collection and return a cursor to the selected documents.
Using $nin
will work, but you have the syntax wrong. It should be:
db.collection.find({'docs.foo': {$nin: [1]}})
Use the $ne
operator:
db.collection.find({'docs.foo': {$ne: 1}})
Update: I'd advise against using $nin
in this case.
{'docs.foo': {$ne: 1}}
takes all elements of docs
, and for each of them it checks whether the foo
field equals 1 or not. If it finds a match, it discards the document from the result list.
{'docs.foo': {$nin: [1]}}
takes all elements of docs
, and for each element it checks whether its foo
field matches any of the members of the array [1]
. This is a Cartesian product, you compare an array to another array, each element to each element. Although MongoDB might be smart and optimize this query, I assume you only use $nin
because "it has do to something with arrays". But if you understand what you do here, you'll realize $nin
is superfluous, and has possibly subpar performance.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With