组和合并对象数组

时间:2019-11-25 14:04:01

标签: mongodb mongodb-query aggregation-framework

我正在努力使用MongoDB的聚合管道功能。 到目前为止,一个结果的输出如下所示:

{
  "type": "inbound",
  "sender": "postAG",
  "receiver": "maxMusterMan",
  "datetime": "20191125",
  "info": [
    {
      "q": "A",
      "value": "5",
      "name": null,
      "plz": 1234
    },
    {
      "q": "B",
      "value": "AS",
      "name": "ABS",
      "plz": null
    },
    {
      "q": "A",
      "value": "5",
      "name": "aa",
      "plz": null
    },
    ... more objects
  ]
}

最终结果应如下:

{
  "type": "inbound",
  "sender": "postAG",
  "receiver": "maxMusterMan",
  "datetime": "20191125",
  "info": [
    {
      "q": "A",
      "value": "0",
      "name": "aa",
      "plz": 1234
    },
    {
      "q": "B",
      "value": "AS",
      "name": "ABS"
    }
  ]
}

因此,简而言之,我想通过“ q”字段将数组字段信息中的值进行分组并合并对象(新对象覆盖旧值)。 此外,我想删除所有值为“”或null的值; 实际有效负载中有更多字段,因此我想避免为对象的每个字段添加$ cond。

有些方法离我很远:

  • 要进行清理,请使用UDF,但这在管道中是不可能的。 使用map-reduce进行分组和合并,这在管道中不可用。
  • 请考虑输入文件是几个管道步骤的输出。 因此,我不能只使用map-reduce,首先我也需要管道。

我的想法是创建两个视图,第一个将做管道工作,第二个将map-reduce,这是一个好的解决方案吗?

Thx 安德烈亚斯

1 个答案:

答案 0 :(得分:0)

根据您的解释,我真的不理解您是否可以使用map-reduce。

但是,假设您不能并且必须“合并”管道,则对于多个字段没有通用的解决方法-您必须为管道中的每个字段创建条件。

话虽如此,这里是一个有效的管道:

db.collection.aggregate(
    [
        {
            "$unwind" : "$info"
        },
        {
            "$group" : {
                "_id" : "$info.q",
                "type" : {
                    "$first" : "$type"
                },
                "sender" : {
                    "$first" : "$sender"
                },
                "receiver" : {
                    "$first" : "$receiver"
                },
                "datetime" : {
                    "$first" : "$datetime"
                },
                "values" : {
                    "$push" : "$info.value"
                },
                "names" : {
                    "$push" : "$info.name"
                },
                "plz" : {
                    "$push" : "$info.plz"
                }
            }
        },
        {
            "$project" : {
                "_id" : 1.0,
                "type" : 1.0,
                "sender" : 1.0,
                "receiver" : 1.0,
                "datetime" : 1.0,
                "values" : {
                    "$filter" : {
                        "input" : "$values",
                        "as" : "curr",
                        "cond" : {
                            "$or" : [
                                {
                                    "$ne" : [
                                        "$$curr",
                                        null
                                    ]
                                },
                                {
                                    "$ne" : [
                                        "$$curr",
                                        ""
                                    ]
                                }
                            ]
                        }
                    }
                },
                "names" : {
                    "$filter" : {
                        "input" : "$names",
                        "as" : "curr",
                        "cond" : {
                            "$or" : [
                                {
                                    "$ne" : [
                                        "$$curr",
                                        null
                                    ]
                                },
                                {
                                    "$ne" : [
                                        "$$curr",
                                        ""
                                    ]
                                }
                            ]
                        }
                    }
                },
                "plz" : {
                    "$filter" : {
                        "input" : "$plz",
                        "as" : "curr",
                        "cond" : {
                            "$or" : [
                                {
                                    "$ne" : [
                                        "$$curr",
                                        null
                                    ]
                                },
                                {
                                    "$ne" : [
                                        "$$curr",
                                        ""
                                    ]
                                }
                            ]
                        }
                    }
                }
            }
        },
        {
            "$project" : {
                "sender" : 1.0,
                "receiver" : 1.0,
                "datetime" : 1.0,
                "type" : 1.0,
                "_id" : 1.0,
                "value" : {
                    "$cond" : {
                        "if" : {
                            "$gt" : [
                                {
                                    "$size" : "$values"
                                },
                                0.0
                            ]
                        },
                        "then" : {
                            "$arrayElemAt" : [
                                "$values",
                                -1.0
                            ]
                        },
                        "else" : null
                    }
                },
                "name" : {
                    "$cond" : {
                        "if" : {
                            "$gt" : [
                                {
                                    "$size" : "$names"
                                },
                                0.0
                            ]
                        },
                        "then" : {
                            "$arrayElemAt" : [
                                "$names",
                                -1.0
                            ]
                        },
                        "else" : null
                    }
                },
                "plz" : {
                    "$cond" : {
                        "if" : {
                            "$gt" : [
                                {
                                    "$size" : "$plz"
                                },
                                0.0
                            ]
                        },
                        "then" : {
                            "$arrayElemAt" : [
                                "$plz",
                                -1.0
                            ]
                        },
                        "else" : null
                    }
                }
            }
        },
        {
            "$addFields" : {
                "infoArray" : [
                    {
                        "k" : "type",
                        "v" : "$_id"
                    },
                    {
                        "k" : "value",
                        "v" : "$value"
                    },
                    {
                        "k" : "name",
                        "v" : "$name"
                    },
                    {
                        "k" : "plz",
                        "v" : "$plz"
                    }
                ]
            }
        },
        {
            "$addFields" : {
                "info" : {
                    "$arrayToObject" : {
                        "$filter" : {
                            "input" : "$infoArray",
                            "as" : "curr",
                            "cond" : {
                                "$ne" : [
                                    "$$curr.v",
                                    null
                                ]
                            }
                        }
                    }
                }
            }
        },
        {
            "$group" : {
                "_id" : null,
                "type" : {
                    "$first" : "$type"
                },
                "sender" : {
                    "$first" : "$sender"
                },
                "receiver" : {
                    "$first" : "$receiver"
                },
                "datetime" : {
                    "$first" : "$datetime"
                },
                "info" : {
                    "$push" : "$info"
                }
            }
        }
    ]
)