我有这样的文件:
{
"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
包括父级的type
展平,如下所示(期望的输出):
"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。
我尝试了很多没有结果的事情。我想知道这是否可行以及如何实现。
答案 0 :(得分:1)
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" } }
}
},
]);
答案 1 :(得分: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"] }
}}
}}
])
答案 2 :(得分:0)
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" } }
}
},
]);
答案 3 :(得分:0)
您可以使用以下汇总。使用$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"}
}}
]
}
}
}
}}
])