gpt4 book ai didi

MongoDB 按键值对聚合/分组

转载 作者:可可西里 更新时间:2023-11-01 09:14:09 26 4
gpt4 key购买 nike

我的数据看起来像这样:

    { 
"_id" : "9aa072e4-b706-47e6-9607-1a39e904a05a",
"customerId" : "2164289-4",
"channelStatuses" : {
"FOO" : {
"status" : "done"
},
"BAR" : {
"status" : "error"
}
},
"channel" : "BAR",
}

我的聚合/组看起来像这样:

    { 
"_id" : {
"customerId" : "$customerId",
"channel" : "$channel",
"status" : "$channelStatuses[$channel].status"
},
"count" : {
"$sum" : 1
}
}

所以基本上对于示例数据,该组应该给我一个分组依据:

   {"customerId": "2164289-4", "channel": "BAR", "status": "error"}

但我不能在聚合/组中使用 []-索引。我应该怎么做?

最佳答案

使用 .aggregate() 无法通过当前结构获得所需的结果。您“可以”更改结构以使用数组而不是命名键,而且操作实际上非常简单。

所以像这样的文档:

    { 
"_id" : "9aa072e4-b706-47e6-9607-1a39e904a05a",
"customerId" : "2164289-4",
"channelStatuses" : [
{
"channel": "FOO",
"status" : "done"
},
{
"channel": "BAR",
"status" : "error"
}
],
"channel" : "BAR",
}

然后您可以在现代版本中使用 $filter , $map$arrayElemAt :

    { "$group": {
"_id": {
"customerId" : "$customerId",
"channel" : "$channel",
"status": {
"$arrayElemAt": [
{ "$map": {
"input": { "$filter": {
"input": "$chanelStatuses",
"as": "el",
"cond": { "$eq": [ "$$el.channel", "$channel" ] }
}},
"as": "el",
"in": "$$el.status"
}},
0
]
}
},
"count": { "$sum": 1 }
}}

旧版本的 MongoDB 将需要 $unwind 来访问匹配的数组元素。

在 MongoDB 2.6 中,您仍然可以在展开之前“预过滤”数组:

[
{ "$project": {
"customerId": 1,
"channel": 1,
"status": {
"$setDifference": [
{ "$map": {
"input": "$channelStatuses",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.channel", "$channel" ] },
"$$el.status",
false
]
}
}},
[false]
]
}
}},
{ "$unwind": "$status" },
{ "$group": {
"_id": {
"customerId": "$customerId",
"channel": "$channel",
"status": "$status"
},
"count": { "$sum": 1 }
}}
]

$unwind 之后“过滤”之前的所有内容:

[
{ "$unwind": "$channelStatuses" },
{ "$project": {
"customerId": 1,
"channel": 1,
"status": "$channelStatuses.status",
"same": { "$eq": [ "$channelStatuses.status", "$channel" ] }
}},
{ "$match": { "same": true } },
{ "$group": {
"_id": "$_id",
"customerId": { "$first": "$customerId" },
"channel": { "$first": "$channel" },
"status": { "$first": "$status" }
}},
{ "$group": {
"_id": {
"customerId": "$customerId",
"channel": "$channel",
"status": "$status"
},
"count": { "$sum": 1 }
}}
]

在低于 MongoDB 2.6 的版本中,您还需要 $project 两个字段之间相等性测试的结果,然后在单独的结果上 $match阶段。您可能还会注意到“两个”$group 阶段,因为第一个阶段通过 $first 过滤后删除了所有可能重复的 “channel” 累加器。以下 $group 与前面的 list 完全相同。

但是如果您不能更改结构并且需要“灵活”匹配不能提供每个名称的键,那么您必须使用 mapReduce:

db.collection.mapReduce(
function() {
emit({
"customerId": this.customerId,
"channel": this.channel,
"status": this.channelStatuses[this.channel].status
},1);
},
function(key,values) {
return Array.sum(values);
},
{ "out": { "inline": 1 } }
)

当然你可以在哪里使用那种符号

关于MongoDB 按键值对聚合/分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36061475/

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