[英]How to use $lookup on array of subdocuments
我有这些架构:
const chatbots = new Schema({
name: String,
campaigns: [{
name: String,
channels: [{
_id: String,
name: String,
budget: Number
}]
}]
});
const chatbotusers = new Schema({
name: String,
campaign_channel: String
})
我需要获得一个活动列表,其中对于每个频道,我有 ChatbotUsers 的总数。 像这样的东西:
[
{
"name": "Campaign #1",
"channels": {
"_id": "eyRyZ1gD0",
"name": "Channel #1",
"users": 10
}
},
{
"name": "Campaign #1",
"channels": {
"_id": "tsKH7WxE",
"name": "Channel #2",
"users": 4
}
}
]
有任何想法吗?
我得到的最远的是这样的:
{
$lookup: {
from: "chatbotusers",
localField: "channels._id",
foreignField: "campaign_channel",
as: "users",
}
},
{
$project: {
name: "$name",
channels: {
$map: {
input: "$channels",
as: "channel",
in: {
_id: "$$channel._id",
name: "$$channel.name",
users: { $size: "$users" },
}
}
}
}
}
但它汇总了营销活动的用户,而不是频道。
(对不起,如果问题标题不合适,我什至不知道如何正确提问)
你可以试试这个查询:
db.chatbots.aggregate([
{
$lookup: {
from: "chatbotusers",
localField: "campaigns.channels._id",
foreignField: "campaign_channel",
as: "users"
}
},
{
$addFields: {
campaigns: {
$map: {
input: "$campaigns",
as: "eachCampaign",
in: {
$mergeObjects: ['$$eachCampaign', {
channels:
{
$reduce: {
input: "$$eachCampaign.channels",
initialValue: [],
in: {
$concatArrays: [
"$$value",
[
{
$mergeObjects: [
"$$this",
{
user: {
$size: {
$filter: {
input: "$users",
as: "e",
cond: {
$eq: [
"$$e.campaign_channel",
"$$this._id"
]
}
}
}
}
}
]
}
]
]
}
}
}
}]
}
}
}
}
},
{
$project: {
users: 0
}
}
])
注意:可以有多种方法来做到这一点,但通过这种方式,我们正在处理来自聊天机器人集合的相同数量的文档,而不是通过执行$unwind
来分解文档,这在您拥有庞大的数据集时可能会有所帮助。
上面的查询应该可以为您提供所需的信息,但无论如何,如果它很慢或者您想增强它,那么在这里:
{
user: {
$size: {
$filter: {
input: "$users", as: "e",
cond: {
$eq: [
"$$e.campaign_channel",
"$$this._id"
]
}
}
}
}
}
我们在每个广告系列中的每个频道遍历users数组的地方,因此而不是每次都在查找后迭代 - 您可以使用reduce
迭代用户一次以获取每个唯一的Campaign_channel 的计数,将此数据替换为users数组,即您可以直接获取用户数的方式。 通常,上述查询的主要目的是保留原始文档结构,使用较少的阶段。
或者,您可以使用此查询,它不会保留原始文档结构(输出中的文档数量也可能超过您收集的文档数量),但可以执行您需要的操作:
db.chatbots.aggregate([
{
$unwind: "$campaigns"
},
{
$unwind: "$campaigns.channels"
},
{
$lookup: {
from: "chatbotusers",
localField: "campaigns.channels._id",
foreignField: "campaign_channel",
as: "users"
}
},
{
$addFields: {
"channels": "$campaigns.channels",
campaigns: "$campaigns.name"
}
},
{
$addFields: {
"channels.users": {
$size: "$users"
}
}
},
{
$project: {
users: 0
}
}
])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.