查找包含文档数组中的字段的子文档

时间:2016-01-18 16:15:51

标签: mongodb mongoose pymongo

假设我有以下persons集合:

{
  "_id": ObjectId("569d07a38e61973f6aded134"),
  "name": "john",
  "pets": [
    {
      "name": "spot",
      "type": "dog",
      "special": "spot eye"
    },
    {
      "name": "bob",
      "type": "cat",
    }
  ]
},
{
  "_id": ObjectId("569d07a38e61973f6aded135"),
  "name": "susie",
  "pets": [
    {
      "name": "fred",
      "type": "cat",
    }
  ]
}

如何找回有special字段的宠物的人?我希望返回的pets数组只包含带有special字段的宠物。

例如,上述集合的预期结果将是:

{
  "_id": ObjectId("569d07a38e61973f6aded134"),
  "name": "john",
  "pets": [
    {
      "name": "spot",
      "type": "dog",
      "special": "spot eye"
    }
  ]
}

我试图用pymongo进行一次查询,尽管即使只是一个有效的MongoDB或mongoose查询也很可爱。

我试图开始:

db.persons.find({pets:{special:{$exists:true}}});

但是已经返回0条记录,即使应该有一些。

2 个答案:

答案 0 :(得分:1)

如果数组包含嵌入的文档,您可以使用dot notation查询嵌入文档中的特定字段。

没有点表示法,您正在查询数组文档以获得完整匹配。

尝试以下查询:

db.persons.find({'pets.special':{$exists:true}});

答案 1 :(得分:1)

您可以使用 aggregation framework 来获得所需的结果。运行以下聚合管道:

db.persons.aggregate([
    {
        "$match": {
            "pets.special": { "$exists": true }
        }
    },
    {
        "$project": {
            "name": 1,             
            "pets": {
                "$setDifference": [
                    {
                        "$map": {
                            "input": "$pets",
                            "as": "el",
                            "in": {
                                "$cond": [
                                    { "$gt": [ "$$el.special", null ] },

                                    "$$el", false 
                                ]
                            }
                        }
                    },
                    [false]
                ]
            }
        }
    }
])

示例输出

{
    "result" : [ 
        {
            "_id" : ObjectId("569d07a38e61973f6aded134"),
            "name" : "john",
            "pets" : [ 
                {
                    "name" : "spot",
                    "type" : "dog",
                    "special" : "spot eye"
                }
            ]
        }
    ],
    "ok" : 1
}

产生重大影响的运营商是 $setDifference $map 运营商。 $map 运算符本质上创建了一个新的数组字段,该字段通过子表达式中的计算逻辑将数值保存到数组的每个元素。 $setDifference 运算符然后返回一个集合,其中的元素出现在第一个集合中但不出现在第二个集合中;即执行第二组相对于第一组的相对补码。在这种情况下,它将基于条件运算符 $cond <返回基于pets属性的存在而具有与父文档无关的元素的最终special数组。 / strong>,用于评估比较运算符 $gt 返回的表达式。