MongoDB:make$lookup将其输出放在数组中的对象中



问题

假设我在project-storage集合中有此文档:

{
name: 'storage',
containers: [
{ name: 'container1', items: ['item1', 'item2'] },
{ name: 'container2', items: ['item2', 'item3'] },
],
}

这些在project-items集合中:

{ name: 'item1', value: 1 },
{ name: 'item2', value: 1 },
{ name: 'item3', value: 1 },

我想编写一个查询,读取storage文档并内联容器中每个container的项,以获得以下内容:

{
name: 'storage',
containers: [
{
name: 'container1',
items: ['item1', 'item2'],
_inlinedItems: [{ name: 'item1', value: 1 }, { name: 'item2', value: 1 }]
},
{
name: 'container2',
items: ['item2', 'item3'],
_inlinedItems: [{ name: 'item2', value: 1 }, { name: 'item3', value: 1 }]
},
],
}

尝试失败

使用aggregate$lookup运算符,我尝试了以下操作:

[
{ $match: { name: 'storage' } },
{
$lookup: {
from: 'project-items',
localField: 'containers.items',
foreignField: 'name',
as: 'containers._inlinedItems',
},
},
]

这不起作用,因为1(它完全擦除container字段,2(它混合了两个容器中的项目:

{
name: 'storage',
containers: {
_inlinedItems: [{ name: 'item1', value: 1 }, { name: 'item2', value: 1 }, { name: 'item3', value: 1 }]
}
}

有没有一种方法可以做到这一点,例如在$lookup运算符的as字段中放入一些特殊的东西?


不满意的解决方案

我能做的最好的事情是unwindcontainers,进行查找,然后group将文档重新组合在一起:

[
{ $match: { name: 'storage' } },
{ $unwind: '$containers' },
{
$lookup: {
from: 'project-items',
localField: 'containers.items',
foreignField: 'name',
as: 'containers._inlinedItems',
},
},
{
$group: {
_id: '$_id' ,
name: { $first: '$name' },
containers: { $push: '$containers' },
},
},
]

这很有效,但我必须列出存储文档中我想要保留的所有属性(例如这里的name(,这在我的情况下是非常有问题的,因为我不知道所有属性的名称,但我确实需要保留它们。


正确的解决方案

我是不是错过了一些显而易见的东西?有没有一种方法可以指定给$lookup操作符,我希望它在container元素中写入,它从中读取项目?还是unwind+group是唯一的方法?

你可以在没有$unwind的情况下尝试,我没有比较两者的性能,但你可以检查一下,如果这对你有帮助的话,

  • $match您的状况
  • $lookup带项目和进入项目数组
  • $project显示必填字段
  • containers上的$map使用$filter对项进行循环和doo过滤,并检查条件是否匹配项,然后在_inlinedItems中返回,然后使用$mergeObjects将对象与当前索引对象合并
{ $match: { name: "storage" } },
{
$lookup: {
from: "project-items",
localField: "containers.items",
foreignField: "name",
as: "items"
}
},
{
$set: {
containers: {
$map: {
input: "$containers",
as: "c",
in: {
$mergeObjects: [
"$$c",
{
_inlinedItems: {
$filter: {
input: "$items",
cond: { $in: ["$$this.name", "$$c.items"] }
}
}
}
]
}
}
}
}
},
{ $project: { items: 0 } }

游乐场

最新更新