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

Looking for sub-documents containing a field in a document's array

假设我有以下 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 条记录,尽管应该有一些。

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

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

尝试以下查询:

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

您可以使用 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 and $map operators. The $map operator in essence creates a new array field that holds values as a result of the evaluated logic in a subexpression to each element of an array. The $setDifference operator then returns a set with elements that appear in the first set but not in the second set; i.e. performs a relative complement of the second set relative to the first. In this case it will return the final pets array that has elements not related to the parent documents based on the existence of the special property, based on the conditional operator $cond which evaluates the expression returned by the comparison operator $gt.