我有一个 mongo 集合(表),其中包含以下形式的文档:
{
"tableName": "Items",
"rows": [
{
"label": "row 1 label here",
"items": ["item1", "item2", "item3"]
},
{
"label": "row 2 label here",
"items": ["item4", "item5", "item6"]
}
]
}
我还有另一个集合(项目),其中包含以下形式的文档:
{
"id": "item1",
"name": "Item name",
"code": "XXX-XXXX-XXXX",
"price": 100
}
现在我想查询给定表中的所有项目,因此我使用以下聚合:
{
"$lookup": {
from: "items",
localField: "rows.items",
foreignField: "id",
as: "rows.items"
}
}
所以我希望所有的“item1”,“item2”,...都被替换为相应的文档:
{
"tableName": "Items",
"rows": [
{
"label": "row 1 label here",
"items": [
{
"id": "item1",
"name": "Item name",
"code": "XXX-XXXX-XXXX",
"price": 100
},
... // the rest of the items
]
},
... // the rest of the rows
]
}
但是,“rows”作为对象返回,仅包含预期数组中的第一个对象,并且标签字段甚至消失了:
{
"tableName": "Items",
"rows": { // <-- rows is returned as on object, should be array
"items": [ // <-- the "label" field is missing
{
"id": "item1",
"name": "Item name",
"code": "XXX-XXXX-XXXX",
"price": 100
},
... // the rest of the items
]
}
}
那么如何保留外部数组和缺失的字段?
这就是我个人反对使用嵌套数组的原因。它给查询带来了不必要的复杂性。
您可能需要在
$unwind
和 rows
级别上 rows.items
两次才能展平阵列。使用查找结果执行 $lookup
和 $mergeObjects
。然后,您需要执行 2 $group
才能恢复到原始结构。
db.tables.aggregate([
{
"$unwind": "$rows"
},
{
"$unwind": "$rows.items"
},
{
"$lookup": {
"from": "items",
"localField": "rows.items",
"foreignField": "id",
"as": "itemsLookup"
}
},
{
"$unwind": "$itemsLookup"
},
{
"$set": {
"rows": {
"$mergeObjects": [
"$rows",
"$itemsLookup"
]
}
}
},
{
"$group": {
"_id": {
"_id": "$_id",
"label": "$rows.label"
},
"tableName": {
"$first": "$tableName"
},
"rows": {
"$push": "$rows"
}
}
},
{
"$group": {
"_id": "$_id._id",
"tableName": {
"$first": "$tableName"
},
"rows": {
"$push": {
"label": "$_id.label",
"items": "$rows"
}
}
}
}
])
如果您发现自己经常在
rows.items
级别工作,请考虑重构架构以将条目存储为单独的文档,例如 this。您也可以通过索引获得潜在的性能提升。