【问题标题】:Looking for sub-documents containing a field in a document's array在文档数组中查找包含字段的子文档
【发布时间】:2016-04-23 21:27:03
【问题描述】:

假设我有以下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 或猫鼬查询也会很可爱。

我尝试过:

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

但它返回了 0 条记录,即使应该有一些。

【问题讨论】:

    标签: mongodb mongoose pymongo


    【解决方案1】:

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

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

    尝试以下查询:

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

    【讨论】:

    • 谢谢。这确实适用于mongo 终端,但由于某种原因,以下pymongo 查询返回完整数组,包括那些没有special 的数组:mperson.find( {"pets.special": { "$exists":"true" }} )。知道为什么吗?
    • 你需要使用python布尔值True而不是字符串“true”:mperson.find( {"pets.special": { "$exists": True }} )
    【解决方案2】:

    您可以使用 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 运算符然后返回一个集合,其中包含出现在第一个集合中但不在第二个集合中的元素;即相对于第一组执行第二组的相对补充。在这种情况下,它将返回最终的 pets 数组,其中包含与父文档无关的元素,基于 special 属性的存在,基于条件运算符 $cond 评估比较运算符返回的表达式 $gt

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-12-11
      • 1970-01-01
      • 1970-01-01
      • 2016-03-12
      • 2016-06-18
      • 1970-01-01
      相关资源
      最近更新 更多