You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mongoose find查询如何过滤返回结果中answers数组内的空对象

问题场景

当前执行如下Mongoose查询代码:

const response = await simpleSurveyResponsesModel
        .find({
          "metaKey.projectId": 7,
        })
        .select([
          "answers.SEC.text",
          "answers.S4.text",
          "answers.S3_a.text",
          "answers.Urban_City.text"
        ])
        .lean();

其中answers字段为对象数组,数组中同时存在空对象与非空对象。

问题描述

使用collection.find()查询时,指定select的字段会正常返回,但answers数组中会同时返回不需要的空对象。
当前实际输出示例:

{
    "_id": "61840979fcbea215bc61ed03",
    "answers": [
        {},
        {},
        {
            "Urban_City": {
                "text": "Hyderabad"
            }
        }
    ]
 }

期望输出为过滤掉answers数组内空对象的结果,仅保留非空对象条目,示例如下:

{
    "_id": "61840979fcbea215bc61ed03",
    "answers": [
        {
            "Urban_City": {
                "text": "Hyderabad"
            }
        }
    ]
 }

需要实现查询约束,让find返回结果的数组字段仅包含非空对象,排除空对象条目。

解决方案

提供两种可落地的实现方式,可根据业务场景选择:

方案1:数据库层面聚合过滤(推荐,性能更优)

通过MongoDB聚合管道的$filter操作符直接在查询阶段完成数组过滤,不会返回冗余空对象数据,适合数据量较大的场景。

const response = await simpleSurveyResponsesModel.aggregate([
  // 匹配原有查询条件
  {
    $match: {
      "metaKey.projectId": 7
    }
  },
  {
    $project: {
      answers: {
        $filter: {
          input: {
            // 先映射数组,仅保留原有select指定的字段
            $map: {
              input: "$answers",
              as: "ans",
              in: {
                "SEC.text": "$$ans.SEC.text",
                "S4.text": "$$ans.S4.text",
                "S3_a.text": "$$ans.S3_a.text",
                "Urban_City.text": "$$ans.Urban_City.text"
              }
            }
          },
          as: "filteredAns",
          // 过滤条件:保留存在目标字段的非空对象
          cond: {
            $or: [
              { $ne: ["$$filteredAns.SEC", undefined] },
              { $ne: ["$$filteredAns.S4", undefined] },
              { $ne: ["$$filteredAns.S3_a", undefined] },
              { $ne: ["$$filteredAns.Urban_City", undefined] }
            ]
          }
        }
      }
    }
  }
])

方案2:查询结果内存过滤(实现简单)

如果业务数据量小,不需要额外优化查询性能,可以保留原有find查询逻辑,在拿到返回结果后遍历过滤空对象,代码改动量最小。

const response = await simpleSurveyResponsesModel
  .find({
    "metaKey.projectId": 7,
  })
  .select([
    "answers.SEC.text",
    "answers.S4.text",
    "answers.S3_a.text",
    "answers.Urban_City.text"
  ])
  .lean();

// 遍历结果过滤answers数组中的空对象
const filteredResult = response.map(item => ({
  ...item,
  answers: item.answers.filter(ans => Object.keys(ans).length > 0)
}))

内容的提问来源于stack exchange,提问作者Haseeb Sheikh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.18 16:15:43