在聚合操作中展开MongoDB嵌套数组

8

我有这样的文件:

{
    "many" : {},
    "other" : {},
    "fields" : {},
    "phases" : [ 
        {
            "type" : 10,
            "states" : [ 
                {
                    "type" : 10,
                    "time" : ISODate("2018-04-25T13:06:42.990+02:00")
                }, 
                {
                    "type" : 20,
                    "time" : ISODate("2018-04-25T13:26:12.122+02:00")
                }, 
                {
                    "type" : 30,
                    "time" : ISODate("2018-04-25T13:26:30.124+02:00")
                }
            ]
        }, 
        {
            "type" : 20,
            "states" : [ 
                {
                    "type" : 10,
                    "time" : ISODate("2018-04-25T13:27:58.201+02:00")
                }
            ]
        }
    ]
}

在聚合中,我尝试将包括父级类型状态扁平化,如下所示(期望输出):

"states" : [ 
    {
        "phase": 10,
        "type" : 10,
        "time" : ISODate("2018-04-25T13:06:42.990+02:00")
    }, 
    {
        "phase": 10,
        "type" : 20,
        "time" : ISODate("2018-04-25T13:26:12.122+02:00")
    }, 
    {
        "phase": 10,
        "type" : 30,
        "time" : ISODate("2018-04-25T13:26:30.124+02:00")
    }, 
    {
        "phase": 20,
        "type" : 10,
        "time" : ISODate("2018-04-25T13:27:58.201+02:00")
    }
]

我已经使用以下聚合完成了额外的states字段,但没有phase字段:

db.docs.aggregate([
{
    $addFields: {
        states: {
            $reduce: {
                  input: "$phases",
                  initialValue: [],
                  in: { $concatArrays: ["$$value", "$$this.states"] }
               }
           }
    }
}
])

我认为应该保留“许多其他领域”,因此我认为分组不是一个选择。


MongoDB版本是3.4。

我尝试了许多方法都没有结果。我想知道是否可能以及如何实现。

4个回答

8
db.state.aggregate(

// Pipeline
[
    // Stage 1
    {
        $unwind: {
            path : "$phases",
            includeArrayIndex : "arrayIndex", // optional
            preserveNullAndEmptyArrays : false // optional
        }
    },

    // Stage 2
    {
        $unwind: {
            path : "$phases.states",
            includeArrayIndex : "arrayIndex", // optional
            preserveNullAndEmptyArrays : false // optional
        }
    },

    // Stage 3
    {
        $project: {
            "phases":"$phases.type",
            "type":"$phases.states.type",
            "time":"$phases.states.time",
        }
    },

    // Stage 4
    {
        $group: {
            "_id":"$_id",
            states: { $push:  { phases: "$phases", type: "$type",time: "$time" } }
        }
    },
]);

4
你可以使用以下聚合方法。使用$map来格式化状态数组,以包含阶段字段。
db.docs.aggregate([
  {"$addFields":{
    "states":{
      "$reduce":{
        "input":"$phases",
        "initialValue":[],
        "in":{
          "$concatArrays":[
            "$$value",
            {"$map":{
              "input":"$$this.states",
              "as":"state",
              "in":{"phase":"$$this.type","type":"$$state.type","time":"$$state.time"}
            }}
          ]
        }
      }
    }
  }}
])

1

您需要使用$map循环遍历每个数组,然后可以使用$reduce将最终数组$concat在一起。

db.collection.aggregate([
  { "$addFields": {
    "states": { "$reduce": {
      "input": { "$map": {
        "input": "$phases",
        "as": "pa",
        "in": { "$map": {
          "input": "$$pa.states",
          "as": "st",
          "in": { "type": "$$st.type", "time": "$$st.time", "phase": "$$pa.type" }
        }}
      }},
      "initialValue": [],
      "in": { "$concatArrays": ["$$value", "$$this"] }
    }}
  }}
])

1
Mohit Kumar Bordia的代码看起来很棒。此外,如果您还想返回旧对象(基于Mohit的代码):
db.getCollection('flatten').aggregate(

// Pipeline
[
    // Stage 1
    {
        $unwind: {
            path : "$phases",
            includeArrayIndex : "arrayIndex", // optional
            preserveNullAndEmptyArrays : false // optional
        }
    },

    // Stage 2
    {
        $unwind: {
            path : "$phases.states",
            includeArrayIndex : "arrayIndex", // optional
            preserveNullAndEmptyArrays : false // optional
        }
    },

    // Stage 3
    {
        $project: {
            "_id" : "$_id",
            "many" : "$many",
            "other" :"$other",
            "fields" : "$fields",
            "phases":"$phases.type",
            "type":"$phases.states.type",
            "time":"$phases.states.time",
        }
    },

    // Stage 4
    {
        $group: {
            "_id":"$_id",
            many : { $first: "$many"},
            other: { "$first": "$other" },
            fields: { "$first": "$fields" },
            states: { $push:  { phases: "$phases", type: "$type",time: "$time" } }
        }
    },
]);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接