我正在与 mongo 合作,目前面临一个我完全无法弄清楚的问题。
我们有 2 个集合,我们正在对第一个集合进行聚合,并对第二个集合进行查找
这是集合形状的示例
// document item in collection Items
let item = {
...
category: ObjectId('A')
}
// document partner in collection Partners
let partner = {
...
supportedCategories: [{ category: ObjectId('A'), active: true }, ...]
}
其背后的目的是获取所有 ITEMS,在其上添加一个名为“合作伙伴”的字段,其中包含 supportCategories 数组中具有匹配类别且活动标志为 true 的合作伙伴列表
现在我们有这个没有管道的 $lookup,它检索与类别 ID 匹配的所有合作伙伴,但不考虑其他布尔值
{
$lookup: {
from: 'partners',
localField: 'category',
foreignField: 'supportedCategories.category',
as: 'joinedPartners',
},
},
我现在在将另一场比赛添加到“活动”中时遇到问题。我尝试了很多不同的事情但没有成功..我尝试的最新查找是
{
$lookup: {
from: "partners",
let: {
mycat: "$category"
},
pipeline: [
{
$match: {
supportedCategories: {
$elemMatch: {
category: '$$mycat',
active: true
}
}
},
},
],
as: "joinedPartners"
}
}
因此,在最后一次尝试中,失败的实际上是类别的匹配:'$$mycat'.. active:true 工作正常,如果我将 '$$mycat' 替换为硬编码值,则一切都完全正确,例如
category: ObjectId('65282c77bcad9b5380acfa28')
。所以我想我不知道如何使用存储在“let”地图上的值。
关于我做错了什么或者我在这里错过了什么有任何线索吗?
使用 $projection、$expr、$elemMatch 尝试了几种不同的替代方案。无法让它匹配两个字段
在
$lookup
子管道中,您可以使用 $map
通过条件检查将数组条目映射到布尔数组。然后,使用 $anyElementTrue
对结果数组进行过滤,进行过滤。
db.items.aggregate([
{
"$match": {
"category": "A"
}
},
{
"$lookup": {
"from": "partners",
"let": {
"mycat": "$category"
},
"pipeline": [
{
"$match": {
"$expr": {
"$anyElementTrue": {
"$map": {
"input": "$supportedCategories",
"as": "cat",
"in": {
$and: [
{
$eq: [
"$$cat.category",
"$$mycat"
]
},
{
$eq: [
true,
"$$cat.active"
]
}
]
}
}
}
}
}
}
],
as: "joinedPartners"
}
}
])