在 MongoDB 中查找包含数组但不包含具有特定字段值的文档的文档

我试图找到所有不包含至少一个具有特定字段值的文档。例如,下面是一个示例集合:

{  _id : 1,
docs : [
{ foo : 1,
bar : 2},
{ foo : 3,
bar : 3}
]
},
{  _id : 2,
docs : [
{ foo : 2,
bar : 2},
{ foo : 3,
bar : 3}
]
}

我希望找到 docs 块中没有包含至少一条 foo = 1记录的文档的每条记录。在上面的示例中,应该只返回第二个文档。

我尝试了以下方法,但它只告诉我是否有不匹配的(返回文档1)。

db.collection.find({"docs": { $not: {$elemMatch: {foo: 1 } } } })

更新: 上面的查询确实有效。很多时候,我的数据是错误的,而不是我的代码。

我也研究了 $nin 操作员,但是示例只在数组包含基元值列表而不是附加文档时显示。当我尝试使用下面这样的代码执行此操作时,它会查找精确的文档,而不仅仅是我想要的 foo 字段。

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

是否有任何方法可以用基本的操作符来实现这一点?

60428 次浏览

使用 $nin是可行的,但是语法错误,应该是:

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

使用 $ne操作符:

db.collection.find({'docs.foo': {$ne: 1}})

更新: 我建议在这种情况下不要使用 $nin

{'docs.foo': {$ne: 1}}获取 docs的所有元素,并对每个元素检查 foo字段是否等于1。如果找到匹配项,它将从结果列表中丢弃该文档。

{'docs.foo': {$nin: [1]}}获取 docs的所有元素,并对每个元素检查其 foo字段是否与数组 [1]的任何成员匹配。这是一个 笛卡儿积,你比较一个数组和另一个数组,每个元素对每个元素。尽管 MongoDB 可能很聪明并且优化了这个查询,但是我假设您只使用 $nin,因为“它对数组做了一些事情”。但是,如果您了解自己在这里所做的工作,您将意识到 $nin是多余的,并且可能性能不佳。