要根据文档值创建对象,我们需要使用$arrayToObject运算符。
优雅的解决方案
解释
- 我们执行
$map
运算符以获得[k:"...", v:"..."]
结构。
- 另外,我们需要计算多少次
emotes
/bounties
重复
db.suggestions.aggregate([
{
$match: {
"channelId": "23435553"
}
},
{
$lookup: {
from: "emotes",
localField: "_id",
foreignField: "suggestionId",
as: "emotes"
}
},
{
$lookup: {
from: "bounties",
localField: "_id",
foreignField: "suggestionId",
as: "bounties"
}
},
{
$project: {
_id: 1,
channelId: 1,
emotes: {
$arrayToObject: {
$map: {
input: "$emotes",
as: "emote",
in: {
k: "$$emote.emoteId",
v: {
$size: {
$filter: {
input: "$emotes",
as: "e",
cond: {
$eq: [
"$$emote.emoteId",
"$$e.emoteId"
]
}
}
}
}
}
}
}
},
bounties: {
$arrayToObject: {
$map: {
input: "$bounties",
as: "bounty",
in: {
k: "$$bounty.userId",
v: {
$sum: {
$map: {
input: {
$filter: {
input: "$bounties",
as: "b",
cond: {
$eq: [
"$$bounty.userId",
"$$b.userId"
]
}
}
},
in: "$$this.bountyAmount"
}
}
}
}
}
}
}
}
}
])
Mongo游乐场
经典解决方案
解释
- 我们需要展平
emotes
/bounties
之后$lookup
。
- 我们执行
$group
阶段以减少重复值
- 我们创建
[{k:"...", v:"..."}]
结构将其转换为Object
with$arrayToObject
运算符。
db.suggestions.aggregate([
{
$match: {
"channelId": "23435553"
}
},
{
$lookup: {
from: "emotes",
localField: "_id",
foreignField: "suggestionId",
as: "emotes"
}
},
{
$unwind: {
path: "$emotes",
preserveNullAndEmptyArrays: true
}
},
{
$group: {
_id: {
"_id": "$_id",
"emoteId": "$emotes.emoteId"
},
channelId: {
$first: "$channelId"
},
count: {
$sum: 1
}
}
},
{
$group: {
_id: "$_id._id",
channelId: {
$first: "$channelId"
},
emotes: {
$push: {
k: "$_id.emoteId",
v: "$count"
}
}
}
},
{
$lookup: {
from: "bounties",
localField: "_id",
foreignField: "suggestionId",
as: "bounties"
}
},
{
$unwind: {
path: "$bounties",
preserveNullAndEmptyArrays: true
}
},
{
$group: {
_id: {
"_id": "$_id",
"userId": "$bounties.userId"
},
channelId: {
$first: "$channelId"
},
emotes: {
$first: "$emotes"
},
bountyAmount: {
$sum: "$bounties.bountyAmount"
}
}
},
{
$group: {
_id: "$_id._id",
channelId: {
$first: "$channelId"
},
emotes: {
$first: "$emotes"
},
bounties: {
$push: {
k: "$_id.userId",
v: "$bountyAmount"
}
}
}
},
{
$project: {
_id: 1,
channelId: 1,
emotes: {
$arrayToObject: "$emotes"
},
bounties: {
$arrayToObject: "$bounties"
},
}
}
])
Mongo游乐场