MongoDB查询排除数组字段

时间:2014-03-19 21:49:09

标签: mongodb

我搜索了一下,但是找不到使用MongoDB的方法 - 或者我只是误解了$ all和$ in运算符。

如果我有以下文件:

{
  arr : ["foo","bar","baz"]
},
{
  arr : ["bar","foo"]
},
{
  arr : ["foo"]
}

我想要一个返回最后两个文档的查询。基本上任何文档只包含["foo", "bar"]的任意组合,但不包含任何其他项目。这是排除方面,我无法弄清楚 - 基本上对于给定的数组,只返回arr字段仅包含该数组中的元素的文档。

> db.foo.find({arr : {"$in" : ["foo", "bar"]}})
{ "_id" : ObjectId("532a0ff6907560a1e88a2c0a"), "arr" : [  "foo",  "bar",  "baz" ] }
{ "_id" : ObjectId("532a0ffc907560a1e88a2c0b"), "arr" : [  "foo",  "bar" ] }
{ "_id" : ObjectId("532a0ffe907560a1e88a2c0c"), "arr" : [  "foo" ] }
> db.foo.find({arr : {"$all" : ["foo", "bar"]}})
{ "_id" : ObjectId("532a0ff6907560a1e88a2c0a"), "arr" : [  "foo",  "bar",  "baz" ] }
{ "_id" : ObjectId("532a0ffc907560a1e88a2c0b"), "arr" : [  "foo",  "bar" ] }
>

这甚至可能吗?我不知道在查询时哪些值是排他性的。

2 个答案:

答案 0 :(得分:4)

您可以通过组合多个运算符来实现此目的:

db.foo.find({arr: {$not: {$elemMatch: {$nin: ['foo', 'bar']}}}})

$elemMatch $nin找到了单个arr元素既不是'foo'也不是'bar'的文档,然后父$not反转了匹配以返回与任何元素不匹配的所有文档。

但是,这也会返回arr缺失或没有元素的文档。要在限定符中排除$and所需的内容,以确保arr至少包含一个元素:

db.foo.find({$and: [
    {arr: {$not: {$elemMatch: {$nin: ['foo', 'bar']}}}},
    {'arr.0': {$exists: true}}
]})

答案 1 :(得分:1)

您可以使用aggregation framework来实现您的目标。查询将类似于:

db.collection.aggregate([
    {$unwind:"$arr"}, 
    {$group:{
        _id:"$_id", 
        // If arr is "foo" or "bar", add 0 to the sum else add 1 to the sum
        exclude:{$sum:{$cond:[{$or:[{$eq:["$arr","foo"]},{$eq:["$arr","bar"]}]},0,1]}}}}, 
    // Exclude all documents where "exclude" count is non-zero
    {$match:{exclude:0}}
])