聚合过滤器从多个数组中返回特定值

时间:2017-06-20 09:55:53

标签: node.js mongodb mongoose aggregation-framework

我有这个json响应结构:

{
    "_id": "5947e320d0f00f1794c87772",
    "selected_product": "5947e320d0f00f1794c87774",
    "sign_in_label": {
        "value": "Sign In",
        "translation": [
            {
                "code": "en",
                "value": "Sign In"
            }
        ]
    },
    "have_account_label": {
        "value": "Already have an account",
        "translation": [
            {
                "code": "en",
                "value": "Already have an account"
            }
        ]
    },
    "sign_up_label": {
        "value": "Sign Up",
        "translation": [
            {
                "code": "en",
                "value": "Sign Up"
            }
        ]
    },
    "products": [
        {
            "value": "Simple Membership",
            "_id": "5947e320d0f00f1794c87774",
            "translation": [
                {
                    "code": "en",
                    "value": "Simple Membership"
                }
            ]
        },
        {
            "value": "Credit Card",
            "_id": "5947e320d0f00f1794c87773",
            "translation": [
                {
                    "code": "en",
                    "value": "Credit Card"
                }
            ]
        }
    ],
    "applying_label": {
        "value": "You're appliying for your",
        "translation": [
            {
                "code": "en",
                "value": "You're appliying for your"
            }
        ]
    },
    "carousel_data": [
        {
            "image": "img1.png",
            "text": {
                "value": "Welcome to your digital banking",
                "translation": [
                    {
                        "code": "en",
                        "value": "Welcome to your digital banking"
                    }
                ]
            }
        },
        {
            "image": "img1.png",
            "text": {
                "value": "Welcome to your digital banking",
                "translation": [
                    {
                        "code": "en",
                        "value": "Welcome to your digital banking"
                    }
                ]
            }
        },
        {
            "image": "img1.png",
            "text": {
                "value": "Welcome to your digital banking",
                "translation": [
                    {
                        "code": "en",
                        "value": "Welcome to your digital banking"
                    }
                ]
            }
        }
    ]
}

我需要使用mongoDB聚合将此json转换为基于转换代码的json结构" en":

{
    "_id": "5947e320d0f00f1794c87772",
    "selected_product": "5947e320d0f00f1794c87774",
    "sign_in_label": "Sign In",
    "have_account_label": "Already have an account",
    "sign_up_label": "Sign Up",
    "products": [
        {
            "value": "Simple Membership",
            "_id": "5947e320d0f00f1794c87774",
        },
        {
            "value": "Credit Card",
            "_id": "5947e320d0f00f1794c87773",
        }
    ],
    "applying_label": "You're appliying for your",
    "carousel_data": [
        {
            "image": "img1.png",
            "text": "Welcome to your digital banking"
        },
        {
            "image": "img1.png",
            "text": "Welcome to your digital banking"
        },
        {
            "image": "img1.png",
            "text": "Welcome to your digital banking"
        }
    ]
}

我已尝试过这条管道,但我坚持使用产品和carousel_data:

var pipeline = [
        {
            $project: {
                sign_in_label: {
                    $filter: {
                        input: "$sign_in_label.translation",
                        as: "sign_in_label",
                        cond: [{ $gte: [ "$sign_in_label.translation.code", "en" ] },
                            "$sign_in_label.translation.value",
                            false]
                    }
                },
                have_account_label: {
                    $filter: {
                        input: "$have_account_label.translation",
                        as: "have_account_label",
                        cond: [{ $gte: [ "$have_account_label.translation.code", "en" ] },
                            "$have_account_label.translation.value",
                            false]
                    }
                },
                sign_up_label: {
                    $filter: {
                        input: "$sign_up_label.translation",
                        as: "sign_up_label",
                        cond: [{ $gte: [ "$sign_up_label.translation.code", "en" ] },
                            "$sign_up_label.translation.value",
                            false]
                    }
                },
                applying_label: {
                    $filter: {
                        input: "$applying_label.translation",
                        as: "applying_label",
                        cond: [{ $gte: [ "$applying_label.translation.code", "en" ] },
                            "$applying_label.translation.value",
                            false]
                    }
                },
                carousel_data:{
                    $filter: {
                        input: "$carousel_data",
                        as: "carousel_data",
                        cond: [{ $gte: [ "$carousel_data.text.translation.code", "en" ] },
                            "$products.translation.value",
                            false]
                    }
                }
            }
        },
        { $unwind: "$sign_in_label" },
        { $unwind: "$have_account_label"},
        { $unwind: "$sign_up_label"},
        { $unwind: "$applying_label"},
        { $group: {
            _id: "$_id",
            sign_in_label: {
                $push: "$sign_in_label.value"
            },
            have_account_label: {
                $push: "$have_account_label.value"
            },
            sign_up_label: {
                $push: "$sign_up_label.value"
            },
            products: {
                $push: "$products"
            },
            applying_label: {
                $push: "$applying_label.value"
            },
            carousel_data:{
                $push: "$carousel_data"
            }
        }},

        { $unwind: "$sign_in_label" },
        { $unwind: "$have_account_label"},
        { $unwind: "$sign_up_label"},
        { $unwind: "$products"},
        { $unwind: "$applying_label"},
        { $unwind: "$carousel_data"}
    ];

使用此管道我有以下回应:

{
"_id": "5947e320d0f00f1794c87772",
"sign_in_label": "Sign In",
"have_account_label": "Already have an account",
"sign_up_label": "Sign Up",
"products": [
    {
        "value": "Simple Membership",
        "_id": "5947e320d0f00f1794c87774",
        "translation": [
            {
                "code": "en",
                "value": "Simple Membership"
            }
        ]
    },
    {
        "value": "Credit Card",
        "_id": "5947e320d0f00f1794c87773",
        "translation": [
            {
                "code": "en",
                "value": "Credit Card"
            }
        ]
    }
],
"applying_label": "You're appliying for your",
"carousel_data": [
    {
        "image": "img1.png",
        "text": {
            "value": "Welcome to your digital banking",
            "translation": [
                {
                    "code": "en",
                    "value": "Welcome to your digital banking"
                }
            ]
        }
    },
    {
        "image": "img1.png",
        "text": {
            "value": "Welcome to your digital banking",
            "translation": [
                {
                    "code": "en",
                    "value": "Welcome to your digital banking"
                }
            ]
        }
    },
    {
        "image": "img1.png",
        "text": {
            "value": "Welcome to your digital banking",
            "translation": [
                {
                    "code": "en",
                    "value": "Welcome to your digital banking"
                }
            ]
        }
    }
]
}

由于我是MongoDB的新手,我觉得我的管道错了。任何人都可以帮忙。

1 个答案:

答案 0 :(得分:0)

你是从正确的轨道开始的,但是有些部分在第一时间难以理解,因此最好通过它们的每个功能来查看它们。

您的整个过程实际上只是一个$project,理想情况下,我认为您需要并且需要使用前面的$match来处理特定文档。由于所有内容都有“翻译”,因此每个字段的代码块基本相同:

*.txt

让我们从缩进中解决:

  • $filter - 指向翻译数组,我们想要的只是语言的“平等”$eq匹配,这里是 "sign_in_label": { "$ifNull": [ { "$arrayElemAt": [ { "$map": { "input": { "$filter": { "input": "$sign_in_label.translation", "as": "el", "cond": { "$eq": [ "$$el.code", "en" ] } } }, "as": "el", "in": "$$el.value" }}, 0 ]}, "$sign_in_label.value" ] }, 。这会将已过滤的数组返回到:

  • $map - 这会将“已过滤”的内容作为输入,并基本上为每个匹配的数组成员返回内部"en",然后将其提供给:

  • $arrayElemAt - 我们的“过滤”和“映射”数组只需要一个元素,并从数组中获取第一个元素,为了喂食:

  • $ifNull - 最终考虑从“已过滤”和“已映射”数组的“第一”位置提取的值。如果未找到此值,则它将为"value",并将null属性替换为“默认值”。

这就是整个事情的组合方式,"value""products"数组只有一点差别,因为它们是数组,我们重新映射“内部”元素。

因此完整的管道是:

"carousel"

将提供输出:

var pipeline = [
  { "$project": {
    "sign_in_label": { 
      "$ifNull": [ 
        { "$arrayElemAt": [
          { "$map": {
            "input": {
              "$filter": {
                "input": "$sign_in_label.translation",
                "as": "el",
                "cond": { "$eq": [ "$$el.code", "en" ] }
              }
            },
            "as": "el",
            "in": "$$el.value"
          }},
          0
        ]}, 
        "$sign_in_label.value"
      ]
    },
    "have_account_label": { 
      "$ifNull": [
        { "$arrayElemAt": [
          { "$map": {
            "input": {
              "$filter": {
                "input": "$have_account_label.translation",
                "as": "el",
                "cond": { "$eq": [ "$$el.code", "en" ] }
              }
            },
            "as": "el",
            "in": "$$el.value"
          }},
          0
        ]},
        "$have_account_label.value"
      ]
    },
    "sign_up_label": { 
      "$ifNull": [
        { "$arrayElemAt": [
          { "$map": {
            "input": {
              "$filter": {
                "input": "$sign_up_label.translation",
                "as": "el",
                "cond": { "$eq": [ "$$el.code", "en" ] }
              }
            },
            "as": "el",
            "in": "$$el.value"
          }},
          0
        ]},
       "$sign_up_label.value"
      ]
    },
    "products": {
      "$map": {
        "input": "$products",
        "as": "el",
        "in": {
          "_id": "$$el._id",
          "value": {
            "$ifNull": [
              { "$arrayElemAt": [
                { "$map": {
                  "input": {
                    "$filter": {
                      "input": "$$el.translation",
                      "as": "t",
                      "cond": { "$eq": [ "$$t.code", "en" ] }
                     }
                   },
                   "as": "t",
                   "in": "$$t.value"
                }},
                0
              ]},
              "$$el.value"
            ]
          }
        }
      }
    },
    "applying_label": { 
      "$ifNull": [
        { "$arrayElemAt": [
          { "$map": {
            "input": {
              "$filter": {
                "input": "$applying_label.translation",
                "as": "el",
                "cond": { "$eq": [ "$$el.code", "en" ] }
              }
            },
            "as": "el",
            "in": "$$el.value"
          }},
          0
        ]},
        "$applying_label.value"
      ]
    },
    "carosel_data": {
      "$map": {
        "input": "$carousel_data",
        "as": "el",
        "in": {
          "image": "$$el.image",
          "text": {
            "$ifNull": [
              { "$arrayElemAt": [
                { "$map": {
                  "input": {
                    "$filter": {
                      "input": "$$el.text.translation",
                      "as": "t",
                      "cond": { "$eq": [ "$$t.code", "en" ] }
                    }
                  },
                  "as": "t",
                  "in": "$$t.value"
                }},
                0
              ]},
              "$$el.text.value"
            ]
          }
        }
      }
    }
  }}
];
相关问题