在嵌入式数组中按$ in查找文档

时间:2015-02-25 12:05:10

标签: mongodb

我有以下文件

{
    "_id": ObjectId("5461363bdfef7c4800146f4b"),
    "title": "Plant Overview",
    "segments": [
        {
            "tagBindings": [
                {
                    "id" : ObjectId("54ac12f4b4f22ec30153ea83"),
                    "tagType" : "Facility"
                }, 
                {
                    "id" : ObjectId("54999a0e899ab5530031535e"),
                    "tagType" : "Facility"
                }, 
                {
                    "id" : ObjectId("5498189c496623160068831c"),
                    "tagType" : "Facility"
                }
            ],
            "name": "Liberty Lofts - Solar Power Plant",
            "id": ObjectId("54637850dfcbe62000a7eddf")
        }
    ]
 }

我想查找segments.tagBindings.id等于某些值并且没有任何其他ID的记录。

我使用该查询:

db.ds_dashboards.find({"segments.tagBindings.id": {$in: [ObjectId("54ac12f4b4f22ec30153ea83"), ObjectId("54999a0e899ab5530031535e")]}})

它返回上面的文档。

但我不需要它,因为第三段.tagBindings.id是5498189c496623160068831c id。

我应该如何更新查询?

2 个答案:

答案 0 :(得分:2)

您希望使用聚合并利用$setIsSubset运算符。所以你的查询看起来像这样:

> db.ds_dashboards.aggregate([
    { "$unwind": "$segments"},
    { "$unwind": "$segments.tagBindings" },
    { "$group": {
        "_id": "$_id",
        "tagBindings" : { "$addToSet": "$segments.tagBindings.id" }
        }
    },
    { "$project": {
        "isValid": {
            "$setIsSubset": [
                "$tagBindings",
                [ObjectId("54ac12f4b4f22ec30153ea83"),
                 ObjectId("54999a0e899ab5530031535e")]
            ]}
        }
    }
]);
{ "_id" : ObjectId("5461363bdfef7c4800146f4b"), "isValid" : false }

如上所示,给定您的示例文档,上面的查询将返回false。这是因为,正如您所说,ObjectId("5498189c496623160068831c")中不存在$tagBindings。如果您修改该数组以包含所述ObjectId,那么它将返回true。

然后,您可以添加match子句来过滤掉isValid为假的结果。最后一个子句看起来像这样:{ "$match": { "isValid": true } }

答案 1 :(得分:1)

首先你应该使用$ all来做这个;

db.ds_dashboards.find({"segments.tagBindings.id": 
{$all:[ObjectId("54ac12f4b4f22ec30153ea83"), ObjectId("54999a0e899ab5530031535e")]}})

你也可以将它与$ size运算符结合使用以获得完全匹配;

db.ds_dashboards.find({"segments.tagBindings.id": 
    {$all:[ObjectId("54ac12f4b4f22ec30153ea83"), ObjectId("54999a0e899ab5530031535e")]},
 "segments.tagBindings": { $size: 2  }})