我正在努力让聚合管道为我提供我在 Mongo 中寻找的确切格式。
我正在使用 unwind,但如果我有一个空数组,我需要使用
preserveNullAndEmptyArrays: true
选项以免丢失对象的其余部分。
但是当我在管道末尾重新组合而不是空数组时,我得到一个带有单个空对象的数组。
我在我的 api 中想出了一个解决方法,但我真的宁愿修复聚合管道。
这是我的例子:
db.produce.aggregate([
{
$unwind: {
path: "$produceItems",
preserveNullAndEmptyArrays: true
}
},
{
$lookup: {
from: "fruits",
localField: "produceItems.item",
foreignField: "_id",
as: "fruitProperties"
}
},
{
$lookup: {
from: "vegetables",
localField: "produceItems.item",
foreignField: "_id",
as: "vegetableProperties"
}
},
{
$addFields: {
"produceItems.properties": {
$ifNull: [
{
$first: "$fruitProperties"
},
{
$first: "$vegetableProperties"
}
]
}
}
},
{
$group: {
_id: "$_id",
produceItems: {
$push: "$produceItems"
}
}
}
])
当数据库对象中的
produceItems = []
时,我希望得到以下响应:
期望的回应:
[
{
"_id": 1,
"produceItems": []
}
]
实际反应:
[
{
"_id": 1,
"produceItems": [
{} // <-- I don't want to get this empty object element in my array
]
}
]
如果我在
produceItems
数组中有任何内容,则管道运行良好,但如果它为空,则管道运行良好。
我的问题似乎是在我的
$addFields
调用中我正在使用子字段。因此父字段会自动创建。
也许我的处理方式是错误的,并且有一种更简单的方法来完成我想做的事情?
您正在 $addFields 阶段显式添加该空对象。
如果我们在查找后结束该管道(Playground),结果是:
{
"_id": 1,
"fruitProperties": [],
"vegetableProperties": []
}
在$addFields(Playground)之后立即结束,结果是:
{
"_id": 1,
"fruitProperties": [],
"produceItems": {}, //<-- this was added by the $addFields
"vegetableProperties": []
}
以这种方式使用字段名称“productItems.properties”是告诉阶段在字段“productItems”中创建一个对象,并有条件地将字段添加到新对象。你真正想要的是有条件地创建对象。
您可以使用“$switch”之类的东西来完成此操作:
{$addFields: {
"produceItems": {
$switch: {
branches: [
{case: {$gt: [0,{$size: "$fruitProperties"}]},
then: {properties: {$first: "$fruitProperties"}}
},
{case: {$gt: [0,{$size: "$vegetableProperties"}]},
then: {properties: {$first: "$vegetableProperties"}}
}
],
default: "$$REMOVE"
}
}
}
}