[英]mongodb - aggregation with $match $in with a $lookup pipeline
[英]MongoDB aggregation $lookup to parent array field with pipeline syntax and _id as string
我的 MongoDB (v.4.4) 中有以下 collections:
guilds
:
{
_id: String,
members: [{ _id String, rank: number },{ _id String, rank: number }...]
}
和characters
:
{
_id: String,
many_other: 'fields'
}
我想加入$lookup
管道语法guild.members <= characters
by _id
字段。
我不使用 Mongo 内置
OjbectIds
作为_id
,我用 collections 中的字符串覆盖它。 正如我所听到的,在管道中使用字符串作为_id
的$lookup
有一些不同的行为。 因此,在回答之前,请确保您对此有所了解。
我想要的预期结果很简单,我想从原始文档中保存排名,并从$lookup
添加任何其他字段:
{
_id: String // (guild)
members: [
{
_id: String, // (characters)
rank: number,
many_other: '...fields from characters'
},
{
_id: String, // (characters)
rank: number,
many_other: '...fields from characters'
}, ...
]
我尝试了什么:
各种查询,例如:
{
$lookup: {
from: "characters",
pipeline: [
{
$match: {
$expr: { $eq: [ { $toString :"$members._id" }, { $toString : "$$character_id" } ] }
}
}
],
as: "guild_members"
},
}
将 ID 转换为字符串,使用let
阶段变量,并使用$map
运算符。 但我离要求的结果还很远。
还有一个问题,和问题有些相关,但和查询本身无关
如您所见, characters
集合还有many other fields
。 其中一些非常重,(因为公会最多可以有 500 个成员)这使得结果文档 >16 MB(MongoDB 阈值限制),这会产生错误。 因为,据我所知,我们无法从joined
的文档中选择字段,所以最好在$lookup
阶段或类似的阶段之后立即排除它。 任何关于它的建议都将非常受欢迎。
当您将members._id
作为 localField 传递时,不需要使用管道查找,
$lookup
与字符和传递members._id
作为 localField$map
迭代members
数组的循环$filter
迭代members_guid
的循环并获取匹配的成员$arrayElemAt
从上面的过滤器中获取第一个匹配元素$mergeObjects
将当前字段与上面过滤的成员 object 合并db.guilds.aggregate([
{
$lookup: {
from: "characters",
localField: "members._id",
foreignField: "_id",
as: "members_guid"
}
},
{
$project: {
members: {
$map: {
input: "$members",
as: "m",
in: {
$mergeObjects: [
"$$m",
{
$arrayElemAt: [
{
$filter: {
input: "$members_guid",
cond: { $eq: ["$$this._id", "$$m._id"] }
}
},
0
]
}
]
}
}
}
}
}
])
我接受@turivishal 的回答,因为旧式原生聚合比pipeline
语法更容易理解。 但如果有人感兴趣,我之前使用过的旧聚合部分。
db.guilds.aggregate([
{
$lookup: {
from: "characters",
let: {
members: "$members"
},
pipeline: [
{
$match: {
$expr: {
$in: [
"$_id",
"$$members._id"
]
}
}
},
{
$addFields: {
rank: {
$reduce: {
input: "$$members",
initialValue: null,
in: {
$cond: [
{
$eq: [
"$$this._id",
"$_id"
]
},
"$$this.rank",
"$$value"
]
}
}
}
}
}
],
as: "members"
},
}
])
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.