【发布时间】:2014-05-25 07:54:27
【问题描述】:
我得到了三份文件:
[
{ _id: 1, article: 1, details: { color: "red" } },
{ _id: 2, article: 1, details: { color: "blue", size: 44 },
{ _id: 3, article: 2, details: { color: "blue", size: 44 }
]
我想在查询中转换为:
[
{ article: 1, details: { color: ["red", "blue"], size: [44] } },
{ article: 2, details: { color: ["blue"], size: [44] }
]
目前这是通过 mapReduce 实现的:
db.varieties.mapReduce(map, reduce, { out: { inline: 1 } });
function map() {
for (var key in this.details) {
this.details[key] = [this.details[key]];
}
emit(this.article, this.details);
}
function reduce(article, details) {
var result = {};
details.forEach(function(detail) {
for (var key in detail) {
if (!Array.isArray(result[key])) result[key] = [];
if (~result[key].indexOf(detail[key])) result[key].concat(detail[key]);
}
});
return result;
}
但是我想通过 mongodb 聚合框架来实现这一点,因为我的环境中的 map reduce 实现非常“困难”。
关于我到目前为止的聚合:
var pipeline = [];
pipeline.push({ $project: { article: 1, details: 1 } });
pipeline.push({ $group: { _id: "$article", details: { $push: '$details' } });
db.varieties.aggregate(pipeline);
但是这只会返回:
[
{ article: 1, details: [{ color: "red", size: 44 }, { color: "blue", size: 44 }] },
{ article: 2, details: [{ color: "blue", size: 44 }]
]
我在某处读到这是$unwind 的用例,不幸的是这不适用于对象。
那么让我们来回答我的问题:
- 是否可以以某种方式将
details对象转换为带有{ key: "color", value: "red" }的数组,如果可以,如何实现? - 如果上述方法不可行,并且我将重组我的文档以以上述格式存储(详细信息为数组),我需要如何完成聚合以从我的原始 mapReduce 获得相同的结果?
我不能硬编码细节的关键。聚合必须处理未知键的详细信息。
【问题讨论】:
标签: mongodb mapreduce aggregation-framework