gpt4 book ai didi

MongoDB 聚合对象映射到不同的值

转载 作者:可可西里 更新时间:2023-11-01 10:04:23 27 4
gpt4 key购买 nike

我得到了三个文件:

[
{ _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 的一个用例,不幸的是这不适用于对象。

那么让我们开始我的问题:

  1. 是否可以通过 { key: "color", value: "red"} 以某种方式将 details 对象转换为数组,如果可以,如何实现?
  2. 如果上述情况不可行,并且我会重组我的文档以按上述格式存储(详细信息为数组),我需要如何完成聚合才能从我的原始 mapReduce 获得相同的结果?

我无法对详细信息的键进行硬编码。聚合必须处理未知键的详细信息。

最佳答案

你最好使用聚合框架:

db.colors.aggregate([
{ "$group": {
"_id": "$article",
"color": {"$addToSet": "$details.color" },
"size": { "$addToSet": "$details.size" }
}},
{ "$project": {
"details": {
"color": "$color",
"size": "$size"
}
}}
])

产生:

{ "_id" : 2, "details" : { "color" : [ "blue" ], "size" : [ 44 ] } }
{ "_id" : 1, "details" : { "color" : [ "blue", "red" ], "size" : [ 44 ] } }

因此当您 $group 时,您不能在“详细信息”下使用这些键但你总是可以 $project到结果中您想要的形式。

聚合框架是 native 代码实现,运行速度比 JavaScript 解释器驱动的 mapReduce 快得多。

但如果你真的需要灵 active ,这个概念是相似的,它只是需要更长的时间,但可以在细节下使用不同的键:

db.colors.mapReduce(
function () {
emit( this.article, this.details );
},
function (key,values) {

var reduced = {
};

values.forEach(function(value) {
for ( var k in value ) {
if ( !reduced.hasOwnProperty(k) )
reduced[k] = [];
if ( reduced[k].indexOf( value[k] ) == -1 )
reduced[k].push( value[k] );
}

});

return reduced;

},
{
"finalize": function(key,value) {

for (var k in value) {
if ( Object.prototype.toString.call( value[k] ) !== '[object Array]') {
var replace = [];
replace.push( value[k] );
value[k] = replace;
}

}

return value;
},
"out": { "inline": 1 }
}
)

但这都是以一种非常“mapReduce”的方式进行的,因此主要字段的值将有所不同。

{ "_id" : 1, "value" : { "color" : [ "blue", "red" ], "size" : [ 44 ] } }
{ "_id" : 2, "value" : { "color" : [ "blue" ], "size" : [ 44 ] } }

关于MongoDB 聚合对象映射到不同的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23853196/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com