Find documents with arrays not containing a docume

2019-01-14 01:09发布

问题:

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?

回答1:

Using $nin will work, but you have the syntax wrong. It should be:

db.collection.find({'docs.foo': {$nin: [1]}})


回答2:

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.



标签: mongodb