MongoDB MapReduce——是否有聚合替代方案?

MongoDB MapReduce——是否有聚合替代方案?,mongodb,mapreduce,aggregation-framework,Mongodb,Mapreduce,Aggregation Framework,我有一个集合,其中的文档使用类似这样的模式(一些成员已编辑): 在此模式中,第一、第二和第三个积极性评级分别对应于媒体数组中的第一、第二和第三个条目。活动评级也是如此。我需要计算集合中所有文档中与其关联的媒体对象的积极性和活动评级的统计信息。现在,我正在使用MapReduce进行此操作。但是,我希望通过聚合管道来实现这一点 理想情况下,我希望同时$解开媒体,答案.评级.积极性,和答案.评级.活动数组,这样我就可以得到基于上一示例的以下三个文档: [ { "_id" : O

我有一个集合,其中的文档使用类似这样的模式(一些成员已编辑):

在此模式中,第一、第二和第三个
积极性
评级分别对应于
媒体
数组中的第一、第二和第三个条目。
活动
评级也是如此。我需要计算集合中所有文档中与其关联的
媒体
对象的
积极性
活动
评级的统计信息。现在,我正在使用MapReduce进行此操作。但是,我希望通过聚合管道来实现这一点

理想情况下,我希望同时
$解开
媒体
答案.评级.积极性
,和
答案.评级.活动
数组,这样我就可以得到基于上一示例的以下三个文档:

[
    {
        "_id" : ObjectId("539f41a95d1887b57ab78bea"),
        "answers" : {
            "ratings" : {
                "positivity" : 2,
                "activity" : 4
            }
        },
        "media" : ObjectId("537ea185df872bb71e4df270")
    },
    {
        "_id" : ObjectId("539f41a95d1887b57ab78bea"),
        "answers" : {
            "ratings" : {
                "positivity" : 3
                "activity" : 4
            }
        },
        "media" : ObjectId("537ea185df872bb71e4df275")
    },
    {
        "_id" : ObjectId("539f41a95d1887b57ab78bea"),
        "answers" : {
            "ratings" : {
                "positivity" : 5
                "activity" : 3
            }
        },
        "media" : ObjectId("537ea185df872bb71e4df272")
    }
]

有什么方法可以做到这一点吗?

当前的聚合框架不允许您这样做。能够解开已知大小相同的多个数组,并为每个数组的第i个值创建一个文档将是一个很好的功能

如果要使用聚合框架,则需要稍微更改模式。例如,以以下文档架构为例:

{
    "_id" : ObjectId("539f41a95d1887b57ab78bea"),
    "answers" : {
        "ratings" : {
            "positivity" : [ 
                {k:1, v:2}, 
                {k:2, v:3}, 
                {k:3, v:5}
            ],
            "activity" : [ 
                {k:1, v:4}, 
                {k:2, v:4}, 
                {k:3, v:3}
            ],
    }},
    "media" : [ 
        {k:1, v:ObjectId("537ea185df872bb71e4df270")}, 
        {k:2, v:ObjectId("537ea185df872bb71e4df275")}, 
        {k:3, v:ObjectId("537ea185df872bb71e4df272")}
    ]
}
通过这样做,实际上就是将索引添加到数组中的对象。在此之后,只需展开所有数组并匹配键即可

db.test.aggregate([{$unwind:"$media"},
{$unwind:"$answers.ratings.positivity"},
{$unwind:"$answers.ratings.activity"},
{$project:{"media":1, "answers.ratings.positivity":1,"answers.ratings.activity":1,
    include:{$and:[
                  {$eq:["$media.k", "$answers.ratings.positivity.k"]},
                  {$eq:["$media.k", "$answers.ratings.activity.k"]}
            ]}}
},
{$match:{include:true}}])
输出为:

[ 
        {
            "_id" : ObjectId("539f41a95d1887b57ab78bea"),
            "answers" : {
                "ratings" : {
                    "positivity" : {
                        "k" : 1,
                        "v" : 2
                    },
                    "activity" : {
                        "k" : 1,
                        "v" : 4
                    }
                }
            },
            "media" : {
                "k" : 1,
                "v" : ObjectId("537ea185df872bb71e4df270")
            },
            "include" : true
        }, 
        {
            "_id" : ObjectId("539f41a95d1887b57ab78bea"),
            "answers" : {
                "ratings" : {
                    "positivity" : {
                        "k" : 2,
                        "v" : 3
                    },
                    "activity" : {
                        "k" : 2,
                        "v" : 4
                    }
                }
            },
            "media" : {
                "k" : 2,
                "v" : ObjectId("537ea185df872bb71e4df275")
            },
            "include" : true
        }, 
        {
            "_id" : ObjectId("539f41a95d1887b57ab78bea"),
            "answers" : {
                "ratings" : {
                    "positivity" : {
                        "k" : 3,
                        "v" : 5
                    },
                    "activity" : {
                        "k" : 3,
                        "v" : 3
                    }
                }
            },
            "media" : {
                "k" : 3,
                "v" : ObjectId("537ea185df872bb71e4df272")
            },
            "include" : true
        }
    ]
这样做会产生大量额外的文档开销,并且可能比当前的MapReduce实现慢。您需要运行测试来检查这一点。根据这三个阵列的大小,所需的计算将以立方体的方式增长。这一点也应牢记在心

[ 
        {
            "_id" : ObjectId("539f41a95d1887b57ab78bea"),
            "answers" : {
                "ratings" : {
                    "positivity" : {
                        "k" : 1,
                        "v" : 2
                    },
                    "activity" : {
                        "k" : 1,
                        "v" : 4
                    }
                }
            },
            "media" : {
                "k" : 1,
                "v" : ObjectId("537ea185df872bb71e4df270")
            },
            "include" : true
        }, 
        {
            "_id" : ObjectId("539f41a95d1887b57ab78bea"),
            "answers" : {
                "ratings" : {
                    "positivity" : {
                        "k" : 2,
                        "v" : 3
                    },
                    "activity" : {
                        "k" : 2,
                        "v" : 4
                    }
                }
            },
            "media" : {
                "k" : 2,
                "v" : ObjectId("537ea185df872bb71e4df275")
            },
            "include" : true
        }, 
        {
            "_id" : ObjectId("539f41a95d1887b57ab78bea"),
            "answers" : {
                "ratings" : {
                    "positivity" : {
                        "k" : 3,
                        "v" : 5
                    },
                    "activity" : {
                        "k" : 3,
                        "v" : 3
                    }
                }
            },
            "media" : {
                "k" : 3,
                "v" : ObjectId("537ea185df872bb71e4df272")
            },
            "include" : true
        }
    ]