mongo 聚合 - 使用preserveNullAndEmptyArrays 展开并使用 subField 进行分组时避免返回空对象

问题描述 投票:0回答:1

我正在努力让聚合管道为我提供我在 Mongo 中寻找的确切格式。

我正在使用 unwind,但如果我有一个空数组,我需要使用

preserveNullAndEmptyArrays: true
选项以免丢失对象的其余部分。

但是当我在管道末尾重新组合而不是空数组时,我得到一个带有单个空对象的数组。

我在我的 api 中想出了一个解决方法,但我真的宁愿修复聚合管道。

Mongo Playground 中的示例

这是我的例子:

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
调用中我正在使用子字段。因此父字段会自动创建。

也许我的处理方式是错误的,并且有一种更简单的方法来完成我想做的事情?

mongodb aggregation-framework
1个回答
0
投票

您正在 $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"
        }
      }
    }
  }

游乐场

© www.soinside.com 2019 - 2024. All rights reserved.