Javascript 如何在MongoDb中将异构数组合并到单个文档中?

Javascript 如何在MongoDb中将异构数组合并到单个文档中?,javascript,python,mongodb,Javascript,Python,Mongodb,我网站的MongoDb为每个用户存储一个文档。每位用户将在访问期间回答两份调查表。表单存储在一个数组中,但由于文档不重叠,一个平面的单个文档就足够了。为了便于分析,我希望制作一个平面表格,列出所有表格中的所有答案 考虑以下数据结构: { "USER_SESSION_ID": 456, "forms": [ { "age": 21, "gender": "m" }, {

我网站的MongoDb为每个用户存储一个文档。每位用户将在访问期间回答两份调查表。表单存储在一个数组中,但由于文档不重叠,一个平面的单个文档就足够了。为了便于分析,我希望制作一个平面表格,列出所有表格中的所有答案

考虑以下数据结构:

{
    "USER_SESSION_ID": 456,
    "forms": [
        {
            "age": 21,
            "gender": "m"
        },
        {
            "job": "Student",
            "years_on_job": "12"
        },
        {
            "Hobby": "Hiking",
            "Twitter": "@my_account"
        }
    ]
},
{
    "USER_SESSION_ID": 678,
    "forms": [
        {
            "age": 46,
            "gender": "f"
        },
        {
            "job": "Bodyguard",
            "years_on_job": "2"
        },
        {
            "Hobby": "Skiing",
            "Twitter": "@bodyguard"
        }
    ]
}
表单文档看起来都不一样,没有冲突的字段,因此我希望将它们合并,生成一个表格式的平面结构,如下所示:

{ 'USER_SESSION_ID': 456, 'age': 21, 'gender': 'm', 'job': 'Student', ... 'Twitter': '@my_account' }
{ 'USER_SESSION_ID': 678, 'age': 46, 'gender': 'f', 'job': 'Bodyguard',  ... 'Twitter': '@bodyguard' }
db.sessions.aggregate(
    {
        '$unwind': '$forms'
    },
    { 
        '$project': {
            'USER_SESSION_ID': true,
            'forms': true
        }
    },
    {
        '$group': {
            '_id': '$USER_SESSION_ID',
            'forms': <magic?!>
        }
    }
)
使用Python,这是一个完全不需要动脑筋的过程,如下所示:

for session in sessions:          # Iterate all docs
    for form in session['forms']: # Iterate all children
        session.update(form)      # Integrate to parent doc
    del session['forms']          # Remove nested child
在MongoDb中,我发现这很难实现。我正在尝试使用聚合管道,我认为它应该适用于此

到目前为止,我通过展开数据结构来帮助自己,如下所示:

{ 'USER_SESSION_ID': 456, 'age': 21, 'gender': 'm', 'job': 'Student', ... 'Twitter': '@my_account' }
{ 'USER_SESSION_ID': 678, 'age': 46, 'gender': 'f', 'job': 'Bodyguard',  ... 'Twitter': '@bodyguard' }
db.sessions.aggregate(
    {
        '$unwind': '$forms'
    },
    { 
        '$project': {
            'USER_SESSION_ID': true,
            'forms': true
        }
    },
    {
        '$group': {
            '_id': '$USER_SESSION_ID',
            'forms': <magic?!>
        }
    }
)
db.sessions.aggregate(
{
“$unwind”:“$forms”
},
{ 
“$project”:{
“用户会话ID”:true,
“形式”:正确
}
},
{
“$group”:{
“\u id”:“$USER\u SESSION\u id”,
‘表格’:
}
}
)
在展开阶段,我为每个子级创建了一个包含父级数据的文档。这应该大致相当于python代码中的double for循环。然而,我觉得我在概念上缺少的是分组时的“合并”累加器。在python中,这是通过
dict.update()
完成的,而在underline.js中则是
扩展(目的地,*源代码)


如何在MongoDB中实现这一点?

尝试以下方法,使用游标的嵌套方法调用来迭代游标结果,并使用以下方法获取
表单
数组中元素的对象键:


我一直在使用聚合管道,直到尝试使用mapReduce命令。这就是我想到的:

db.sessions.mapReduce(
    function () {
        var merged = {};
        this.forms.forEach(function (form) {
            for(var key in form) {
                merged[key] = form[key];
            }
        });
        emit(this.USER_SESSION_ID, merged);
    },
    function () {},
    {
         "out": {"inline": true}
    }
)
映射步骤将组合元素,因为没有单个$merging操作符可用作聚合管道步骤。空
reduce
功能是必需的。
out
要么写入另一个集合,要么只返回结果(内联,我在这里所做的)


这看起来很像克里达姆在回答中展示的方法,但实际上使用了投影。他的版本更接近于我的python代码的工作方式,但对于我试图做的事情,投影是好的,不会改变原始集。请注意,python代码可以做到这一点,但不改变输入集合是非常有用的

谢谢你的回答!我使用mapReduce函数解决了我的问题,它允许进一步处理!我喜欢你和我的python代码有多么接近,我不知道这是可能的!非常感谢@不用担心,很高兴你找到了解决办法。