根据某些其他字段

时间:2017-01-27 11:36:50

标签: mongodb mongodb-query aggregation-framework

概述:

我正在处理的文档中有两个嵌套数组 - contentMetaData& text_content。 在contentMetaData内,我们有text_contentcontent_flag。根据{{​​1}}的值,我需要隐藏content_flag中的特定字段。

要求:

  • 如果text_content为真,则content_flag应该只有一个孩子 - text_content
  • 如果text_note为假,content_flag应该只有一个孩子 - text_content
  • 需要保留结构和其他细节。
  • 文件不应该更新;这些值只需在投影期间隐藏。

使用的版本: Mongo 2.6

示例文档:

text_description

示例输出:

{
  "_id": ObjectId("56f8dd19e4b0365115927b0f"),
  "contentId": "cbc91805-2faa-4eff-8f84-02547173c152",
  "contentMetaData": [
    {
      "_id": "1574b58f-b7fa-4cd5-b34f-98beeb657c97",
      "name": "text_content",
      "attributes": [],
      "children": [
        {
          "_id": "97340ecf-fdbd-41e5-a6b2-01cc542f16ee",
          "name": "text_note",
          "value": "abc",
          "type": "java.lang.String",
          "attributes": [],
          "children": [],
          "noOfChildren": 0,
          "positionIndex": 1
        },
        {
          "_id": "19c5a3fb-54a2-4368-a89d-ea1d2554402d",
          "name": "text_description",
          "value": "def",
          "type": "java.lang.String",
          "attributes": [],
          "children": [],
          "noOfChildren": 0,
          "positionIndex": 2
        }
      ],
      "noOfChildren": 2,
      "positionIndex": 1
    },
    {
      "_id": "4e8ef7c9-cffd-4b36-9109-89b263dff3c8",
      "name": "content_flag",
      "value": "true",
      "type": "java.lang.String",
      "attributes": [],
      "children": [],
      "noOfChildren": 0,
      "positionIndex": 2
    }
  ]
}

我尝试使用{ "_id": ObjectId("56f8dd19e4b0365115927b0f"), "contentId": "cbc91805-2faa-4eff-8f84-02547173c152", "contentMetaData": [ { "_id": "1574b58f-b7fa-4cd5-b34f-98beeb657c97", "name": "text_content", "attributes": [], "children": [ { "_id": "97340ecf-fdbd-41e5-a6b2-01cc542f16ee", "name": "text_note", "value": "abc", "type": "java.lang.String", "attributes": [], "children": [], "noOfChildren": 0, "positionIndex": 1 } ], "noOfChildren": 2, "positionIndex": 1 }, { "_id": "4e8ef7c9-cffd-4b36-9109-89b263dff3c8", "name": "content_flag", "value": "true", "type": "java.lang.String", "attributes": [], "children": [], "noOfChildren": 0, "positionIndex": 2 } ] } 但它没有用。我尝试使用$map,但无法以所需格式$unwind数据。

示例Mongo代码:

$push

我是Mongo的新手。有人可以帮我解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

您可以尝试以下聚合。

$map$setDifference结合使用,可以提取text_contentcontent_flag数组。

$unwindcontent_flag文档。

$maptext_content$map中的当前值与$setDifference结合使用,以便根据条件过滤children

$setUniontext_contentcontent_flag数组加入contentMetaData

db.collection.aggregate({
    $project: {
        _id: 1,
        contentId: 1,
        text_content: {
            "$setDifference": [{
                    "$map": {
                        "input": "$contentMetaData",
                        "as": "text",
                        "in": {
                            "$cond": [{
                                    $eq: ['$$text.name', "text_content"]
                                },
                                "$$text",
                                false
                            ]
                        }
                    }
                },
                [false]
            ]
        },
        content_flag: {
            "$setDifference": [{
                    "$map": {
                        "input": "$contentMetaData",
                        "as": "content",
                        "in": {
                            "$cond": [{
                                    $eq: ['$$content.name', "content_flag"]
                                },
                                "$$content",
                                false
                            ]
                        }
                    }
                },
                [false]
            ]
        }
    }
}, {
    $unwind: "$content_flag"
}, {
    $project: {
        "_id": 1,
        contentId: 1,
        "contentMetaData": {
            $setUnion: [{
                    $map: {
                        input: "$text_content",
                        as: "text",
                        in: {
                            "_id": "$$text._id",
                            "name": "$$text.name",
                            "attributes": "$$text.attributes",
                            "noOfChildren": "$$text.noOfChildren",
                            "positionIndex": "$$text.positionIndex",
                            "children": {
                                "$setDifference": [{
                                        "$map": {
                                            "input": "$$text.children",
                                            "as": "child",
                                            "in": {
                                                "$cond": [{
                                                        "$cond": [{
                                                            $eq: ["$content_flag.value", "true"]
                                                        }, {
                                                            $eq: ["$$child.name", "text_note"]
                                                        }, {
                                                            $eq: ["$$child.name", "text_description"]
                                                        }]
                                                    },
                                                    "$$child",
                                                    false
                                                ]
                                            }
                                        }
                                    },
                                    [false]
                                ]
                            }
                        }
                    }
                },
                ["$content_flag"]
            ]
        }
    }
})

<强>更新

$map$setDifference结合使用以提取content_flag数组。

$unwindcontent_flag文档。

$redact一次浏览一个文档级别,并递归查找name字段,并对条件执行$$DESCEND$$PRUNE

$project格式化最终回复。

db.collection.aggregate({
    $project: {
        _id: 1,
        contentId: 1,
        contentMetaData: 1,
        content_flag: {
            "$setDifference": [{
                    "$map": {
                        "input": "$contentMetaData",
                        "as": "content",
                        "in": {
                            "$cond": [{
                                    $eq: ['$$content.name', "content_flag"]
                                },
                                "$$content",
                                false
                            ]
                        }
                    }
                },
                [false]
            ]
        }
    }
}, {
    $unwind: "$content_flag"
}, {
    $redact: {
        $cond: [{
                $or: [{
                    $eq: ["$name", "text_content"]
                }, {
                    $not: "$name"
                }, {
                    $eq: ["$name", "content_flag"]
                }, {
                    $and: [{
                        $eq: ["$name", "text_note"]
                    }, {
                        $eq: ["$$ROOT.content_flag.value", "true"]
                    }]
                }, {
                    $and: [{
                        $eq: ["$name", "text_description"]
                    }, {
                        $eq: ["$$ROOT.content_flag.value", "false"]
                    }]
                }]
            },
            "$$DESCEND",
            "$$PRUNE"
        ]
    }
}, {
    $project: {
        _id: 1,
        contentId: 1,
        contentMetaData: 1
    }
});