MongoDB:聚合和展平一个数组字段

4
在使用关系型数据库(SQL Server、MySQL、Oracle、Informix)工作了28年之后,我已经转向MongoDB。在过去的两个星期里,进展缓慢。我想提交几个问题来确认我的想法。
我的文档如下所示(忽略此问题的分组):
{
    "_id": "xyz-800",
    "site": "xyz",
    "user": 800,
    "timepoints": [
        {"timepoint": 0, "a": 1500, "b": 700},
        {"timepoint": 2, "a": 1000, "b": 200},
        {"timepoint": 4, "a": 3500, "b": 1500}
    ],
    "groupings": [
        {"type": "MNO", "group": "<10%", "raw": "1"},
        {"type": "IJK", "group": "Moderate", "raw": "23"}
    ]
}

我希望能将嵌套的时间点数组扁平化。以下方法能够实现,但是否有办法用通配符替代timepoints中的属性而不是列出每一个属性呢?原因在于,如果子文档添加了一个新属性(例如'c'),那么我就必须修改代码;或者如果这个子文档有很多属性,我就需要列出每一个属性,而不是使用通配符(如果可能的话)。
db.records.aggregate( {$unwind : "$timepoints"}, 
                      {$project: {_id: 1, site: 1, user: 1, 
                                  'timepoint': '$timepoints.timepoint', 
                                  'a': '$timepoints.a', 
                                  'b': '$timepoints.b'}})

结果:

{"id":"xyz-800", "site":"xyz", "user":800, "timepoint": 0, "a":1500, "b":700}
{"id":"xyz-800", "site":"xyz", "user":800, "timepoint": 2, "a":1000, "b":200}
{"id":"xyz-800", "site":"xyz", "user":800, "timepoint": 4, "a":3500, "b":1500}

我目前使用的是MongoDB 3.2版本。

1个回答

10

从MongoDb 3.4开始,我们可以使用$addFields将顶层字段添加到嵌入式文档中,并使用$replaceRoot将嵌入式文档提升到顶层。

db.records.aggregate({
    $unwind: "$timepoints"
}, {
    $addFields: {
        "timepoints._id": "$_id",
        "timepoints.site": "$site",
        "timepoints.user": "$user"
    }
}, {
    $replaceRoot: {
        newRoot: "$timepoints"
    }
})

示例输出

{ "timepoint" : 0, "a" : 1500, "b" : 700, "_id" : "xyz-800", "site" : "xyz", "user" : 800 }
{ "timepoint" : 2, "a" : 1000, "b" : 200, "_id" : "xyz-800", "site" : "xyz", "user" : 800 }
{ "timepoint" : 4, "a" : 3500, "b" : 1500, "_id" : "xyz-800", "site" : "xyz", "user" : 800 }

非常感谢,我希望有类似'timepoints.*': 1的东西。3.4中有一些有趣的新操作符。 - C. Wolcott

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