我想只查找数组中存在所有'docs.foo'
的文档。
在我的示例中,我应该只获得_id: 2
结果:
{
_id : 1,
docs : [
{ bar : 2},
{ foo : 3, bar : 3}
]
},
{
_id : 2,
docs : [
{ foo : 2, bar : 2},
{ foo : 3, bar : 3}
]
}
我想到了类似的东西:
db.collection.find({'docs.foo': {$nin: [$exists: false]}})
但无法使其发挥作用。
答案 0 :(得分:3)
使用$where
运算符。
db.collection.find(function() {
return this.docs.length === this.docs.filter(function(doc) {
return typeof(doc.foo) !== "undefined" && doc.foo !== null ;}).length
})
另一种方法是运行两个查询:一个查询使用distinct()
方法检索所有不符合条件的文档的_id
:
var unwantedIds = db.collection.distinct( "_id", { "docs": { "$elemMatch": { "foo": { "$exists": false } } } } );
然后使用$nin
运算符返回符合条件的所有文档。
db.collection.find({ "_id": { "$nin": unwantedIds } } )
您也可以使用.aggregate()
方法但这仅适用于3.2或更高版本,因为您需要使用$filter
管道中的第一个阶段是$match
阶段,您可以过滤掉那些" foo"场缺席。这减少了将在管道中处理的文档总数。下一个和最后一个阶段是$redact
阶段。在此阶段,您需要使用$size
运算符来返回" docs"的大小。字段和子文档数组的大小,其中" foo"存在并返回两个值相等的所有文档。
db.collection.aggregate([
{ "$match": { "docs.foo": { "$exists": true } } },
{ "$redact": {
"$cond": [
{ "$eq": [
{ "$size": "$docs" },
{ "$size": {
"$filter": {
"input": "$docs",
"as": "doc",
"cond": {
"$ne": [
{ "$ifNull": [ "$$doc.foo", null ] },
null
]
}
}
}}
]},
"$$KEEP",
"$$PRUNE"
]
}}
])