python - $graphLookup 管道阶段后过滤结果

标签 python mongodb aggregation-framework

我有字段相同的父记录和子记录。然而,某些字段仅在父级别设置。

父字段设置为空字符串 ("") 表示该记录是父记录。其他记录有一个指向父记录的值集,因此这些记录可以被视为子记录。

现在考虑以下记录:

{"_id": 1, parent: "", "pValue": ["a", "b", "c"], fieldA: 2},
{"_id": 2, parent: 1, "pValue": [], fieldA: 2},
{"_id": 3, parent: 1, "pValue": [], fieldA: 2},
{"_id": 4, parent: "", "pValue": ["d"], fieldA: 9},
{"_id": 5, parent: 4, "pValue": [], fieldA:2},
{"_id": 6, parent: 4,"pValue": [], fieldA: 9}

上述记录包含两个父记录,每个父记录有 2 个关联的子记录。我尝试执行的查询涉及匹配两个给定的参数。首先是 pValue 的值。一旦我得到了数组中具有特定 pValue 的所有 parent 。然后,我想要将该父记录及其所有关联的子记录与 fieldA 值相匹配。

因此,如果给定 pValue="d"且 fieldA=9 我希望光标内包含以下记录:

{"_id": 4, parent: "", "pValue": ["d"], fieldA: 9}
{"_id": 6, parent: 4, "pValue": [],fieldA: 9}

注释:

  1. 每个父级都可以有多个与其关联的子级。
  2. 父级可以具有与子级不同的 fieldA 值,并且查询只能返回子级而不是父级

我的尝试:

 cursor=self.pCollection.aggregate([
      { "$match": {"pValue":{"$in":[pCheck]}},
      {   "$graphLookup" : {
          "from": "pCollection",
          "startWith": "$_id",
          "connectFromField": "_id",
          "connectToField": "parent",
          "as" : "children"
          }
      }])

然后,我陷入了所有与父级相关联的子级作为数组的困境,而不知道如何包装它们。

最佳答案

您需要使用 $match 选择与您的查询条件匹配的文档并过滤“children”数组,添加 $addFields阶段。

$filter之后ing,您可以使用arrayElemAt 项目分配给字段。

{ "$match": { "fieldA": 9, "children.fieldA": 9 } },
{ "$addFields": { 
    "children": {
        "$arrayElemAt": [
            { "$filter": { 
                "input": "$children",
                "as": "child",
                "cond": { "$eq": [ "$$child.fieldA", 9 ] }
            }},
            0
         ]
    }
}}

您的查询将产生如下内容:

{
    "_id" : 4,
    "parent" : "",
    "pValue" : [ "d" ],
    "fieldA" : 9,
    "children" : { "_id" : 6, "parent" : 4, "pValue" : [ ], "fieldA" : 9 }
}

但是,只要有一点信心,您就可以获得预期的结果。

db.collection.aggregate([
    { "$graphLookup": {
        "from": "collection",
        "startWith": "$_id", 
        "connectFromField": "_id",           
        "connectToField": "parent",     
        "as" : "children"
    }}, 
    { "$match": { "fieldA": 9, "children.fieldA": 9 } }, 
    { "$addFields": { 
        "children": { 
            "$arrayElemAt": [ 
                { "$filter": { 
                    "input": "$children", 
                    "as": "child", 
                    "cond": { "$eq": [ "$$child.fieldA", 9 ] } 
                }}, 
                0 
            ] 
        }
    }}, 
    { "$project": { 
        "children": [
            "$children", 
            { 
                "_id": "$_id", 
                "parent": "$parent", 
                "pValue": "$pValue", 
                "fieldA": "$fieldA" 
            }
        ]
    }}, 
    { "$unwind": "$children" }, 
    { "$replaceRoot": { "newRoot": "$children" } }
])

它会产生这样的东西:

{ "_id" : 6, "parent" : 4, "pValue" : [ ], "fieldA" : 9 }
{ "_id" : 4, "parent" : "", "pValue" : [ "d" ], "fieldA" : 9 }

坦白说,我不认为这是您应该在应用程序中执行的操作。第一个选项是您可以并且应该接受的。

如果你确实需要这个,我建议你create a view并查询应用程序中的 View 。

关于python - $graphLookup 管道阶段后过滤结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41690606/

相关文章:

Python 方法访问器在每次访问时创建新对象?

c# - 如何在 Mongo 文档中查询字典?

mongodb - 具有不同 $match 的嵌套 $group

javascript - 无法使用 HTTP Put 更新 MongoDB 集合内的对象?

mongodb - Mongoose- 使用特定项目将数组中的数据搜索/过滤到另一个数组中

聚合中的 Mongodb 子查询

mongodb - 在聚合 $group 中使用 $map

python - OpenCV Python 3.3

python - 以编程方式刷新 PATH 中的环境变量引用 (Windows 10)

python - 在 Pandas 中用标量乘以列