Mongodb 聚合行到列
Mongodb Aggregation Rows to Columns
我有以下数据集。我需要按帐户对它们进行分组,然后将 Element_Fieldname
变成一列。
var collection = [
{
Account:12345,
Element_Fieldname:"cars",
Element_Value:true
},
{
Account:12345,
Element_Fieldname:"boats",
Element_Value:false
}
]
这是我尝试将行转换为列的尝试,但它不起作用。
db.getCollection('my_collection').aggregate([{
$match : {
Element_Fieldname : {
$in : ["cars", "boats"]
}
}
}, {
$group : {
_id : "$Account",
values : {
$addToSet : {
field : "$Element_Fieldname",
value : "$Element_Value"
}
}
}
}, {
$project : {
Account : "$_id",
cars : {
"$cond" : [{
$eq : ["$Element_Fieldname", "cars"]
}, "$Element_Value", null]
},
boats : {
"$cond" : [{
$eq : ["$Element_Fieldname", "day_before_water_bottles"]
}, "$Element_Value", null]
},
}
}
])
这只是在我的 cars
和 boats
字段中给了我 null
。任何帮助都会很棒。
这是我想要的结果:
var desiredResult = [
{
Account:12345,
cars:true,
boats:false
}
]
这是一个很大的技巧,但你会得到你需要的:-)
请在聚合管道顶部添加 $match
db.collection.aggregate([{
$project : {
_id : 0,
"Account" : 1,
car : {
$cond : [{
$eq : ["$Element_Fieldname", "cars"]
}, "$Element_Value", null]
},
boats : {
$cond : [{
$eq : ["$Element_Fieldname", "boats"]
}, "$Element_Value", null]
},
}
},
{
$group : {
_id : "$Account",
carData : {
$addToSet : "$car"
},
boatsData : {
$addToSet : "$boats"
}
}
}, {
$unwind : "$carData"
}, {
$match : {
carData : {
$ne : null
}
}
}, {
$unwind : "$boatsData"
}, {
$match : {
boatsData : {
$ne : null
}
}
},
])
和结果
{
"_id" : 12345,
"carData" : true,
"boatsData" : false
}
无法使用聚合框架进行您描述的计算类型,但是有一个建议的 $arrayToObject
表达式可以为您提供功能查看键名,并动态创建新的 key/values。
例如,您可以这样做
db.collection.aggregate([
{
"$match": { "Element_Fieldname":{ "$in": ["cars", "boats"] } }
},
{
"$group": {
"_id": "$Account",
"attrs": {
"$push": {
"key": "$Element_Fieldname",
"val": "$Element_Value"
}
}
}
},
{
"$project": {
"Account": "$_id",
"_id": 0,
"newAttrs": {
"$arrayToObject": {
"$map": {
"input": "$attrs",
"as": "el",
in: ["$$el.key", "$$el.val"]
}
}
}
}
},
{
"$project": {
"Account": 1,
"cars": "$newAttrs.cars",
"boats": "$newAttrs.boats"
}
}
])
为这张 jira 票https://jira.mongodb.org/browse/SERVER-23310投票以获得此功能。
作为解决方法,mapreduce 似乎是可用的选项。考虑 运行 以下 map-reduce 操作:
db.collection.mapReduce(
function() {
var obj = {};
obj[this.Element_Fieldname] = this.Element_Value;
emit(this.Account, obj);
},
function(key, values) {
var obj = {};
values.forEach(function(value) {
Object.keys(value).forEach(function(key) {
obj[key] = value[key];
});
});
return obj;
},
{ "out": { "inline": 1 } }
)
结果:
{
"_id" : 12345,
"value" : {
"cars" : true,
"boats" : false
}
}
我有以下数据集。我需要按帐户对它们进行分组,然后将 Element_Fieldname
变成一列。
var collection = [
{
Account:12345,
Element_Fieldname:"cars",
Element_Value:true
},
{
Account:12345,
Element_Fieldname:"boats",
Element_Value:false
}
]
这是我尝试将行转换为列的尝试,但它不起作用。
db.getCollection('my_collection').aggregate([{
$match : {
Element_Fieldname : {
$in : ["cars", "boats"]
}
}
}, {
$group : {
_id : "$Account",
values : {
$addToSet : {
field : "$Element_Fieldname",
value : "$Element_Value"
}
}
}
}, {
$project : {
Account : "$_id",
cars : {
"$cond" : [{
$eq : ["$Element_Fieldname", "cars"]
}, "$Element_Value", null]
},
boats : {
"$cond" : [{
$eq : ["$Element_Fieldname", "day_before_water_bottles"]
}, "$Element_Value", null]
},
}
}
])
这只是在我的 cars
和 boats
字段中给了我 null
。任何帮助都会很棒。
这是我想要的结果:
var desiredResult = [
{
Account:12345,
cars:true,
boats:false
}
]
这是一个很大的技巧,但你会得到你需要的:-)
请在聚合管道顶部添加 $match
db.collection.aggregate([{
$project : {
_id : 0,
"Account" : 1,
car : {
$cond : [{
$eq : ["$Element_Fieldname", "cars"]
}, "$Element_Value", null]
},
boats : {
$cond : [{
$eq : ["$Element_Fieldname", "boats"]
}, "$Element_Value", null]
},
}
},
{
$group : {
_id : "$Account",
carData : {
$addToSet : "$car"
},
boatsData : {
$addToSet : "$boats"
}
}
}, {
$unwind : "$carData"
}, {
$match : {
carData : {
$ne : null
}
}
}, {
$unwind : "$boatsData"
}, {
$match : {
boatsData : {
$ne : null
}
}
},
])
和结果
{
"_id" : 12345,
"carData" : true,
"boatsData" : false
}
无法使用聚合框架进行您描述的计算类型,但是有一个建议的 $arrayToObject
表达式可以为您提供功能查看键名,并动态创建新的 key/values。
例如,您可以这样做
db.collection.aggregate([
{
"$match": { "Element_Fieldname":{ "$in": ["cars", "boats"] } }
},
{
"$group": {
"_id": "$Account",
"attrs": {
"$push": {
"key": "$Element_Fieldname",
"val": "$Element_Value"
}
}
}
},
{
"$project": {
"Account": "$_id",
"_id": 0,
"newAttrs": {
"$arrayToObject": {
"$map": {
"input": "$attrs",
"as": "el",
in: ["$$el.key", "$$el.val"]
}
}
}
}
},
{
"$project": {
"Account": 1,
"cars": "$newAttrs.cars",
"boats": "$newAttrs.boats"
}
}
])
为这张 jira 票https://jira.mongodb.org/browse/SERVER-23310投票以获得此功能。
作为解决方法,mapreduce 似乎是可用的选项。考虑 运行 以下 map-reduce 操作:
db.collection.mapReduce(
function() {
var obj = {};
obj[this.Element_Fieldname] = this.Element_Value;
emit(this.Account, obj);
},
function(key, values) {
var obj = {};
values.forEach(function(value) {
Object.keys(value).forEach(function(key) {
obj[key] = value[key];
});
});
return obj;
},
{ "out": { "inline": 1 } }
)
结果:
{
"_id" : 12345,
"value" : {
"cars" : true,
"boats" : false
}
}