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

MongoDB递归查询嵌套字段:筛选含指定type的文档返回name

实现方法

由于你的文档嵌套层级不固定,需要递归遍历data字段的所有层级来检查是否存在type="20"的节点,以下是两种可行的方案:

方案1:用$function自定义递归检查函数(MongoDB 4.4+)

这个聚合查询会递归遍历每个文档的data结构,筛选出符合条件的文档并仅返回name字段:

db.collection.aggregate([
  {
    $match: {
      $expr: {
        $function: {
          body: function checkHasType20(obj) {
            // 检查当前节点的type是否为"20"
            if (obj.type === "20") return true;
            // 遍历items数组里的子节点,递归检查
            if (obj.items && Array.isArray(obj.items)) {
              for (const item of obj.items) {
                if (checkHasType20(item)) return true;
              }
            }
            return false;
          },
          args: ["$data"],
          lang: "js"
        }
      }
    }
  },
  {
    $project: {
      _id: 0,
      name: 1
    }
  }
])

工作逻辑:

  • $function定义了一个递归函数,从data对象开始遍历:
    1. 先判断当前节点的type是否等于"20",是则返回true
    2. 如果当前节点有items数组,就逐个递归检查数组里的子节点
    3. 只要任意层级存在符合条件的节点,函数返回true,文档会被$match保留
  • $project阶段只保留name字段,去掉其他无关内容

方案2:迭代式检查(避免递归深度问题)

如果担心递归深度限制(虽然20层完全没问题),可以用栈实现迭代遍历,逻辑和递归一致但更稳妥:

db.collection.aggregate([
  {
    $addFields: {
      hasType20: {
        $function: {
          body: function(obj) {
            const stack = [obj];
            while (stack.length > 0) {
              const current = stack.pop();
              if (current.type === "20") return true;
              if (current.items && Array.isArray(current.items)) {
                stack.push(...current.items);
              }
            }
            return false;
          },
          args: ["$data"],
          lang: "js"
        }
      }
    }
  },
  {
    $match: { hasType20: true }
  },
  {
    $project: { _id: 0, name: 1 }
  }
])

工作逻辑:

  1. 用栈存储待检查的节点,初始时把data对象压入栈
  2. 每次弹出一个节点检查type,符合条件就返回true
  3. 如果节点有items数组,就把所有子节点压入栈继续检查
  4. 最后通过临时字段hasType20筛选符合条件的文档,返回name

注意事项

  • $function需要MongoDB 4.4及以上版本,如果你用的是更低版本,只能用Map-Reduce(效率较低)或者提前扁平化数据结构
  • 数据量很大时,JavaScript函数的性能会比原生操作符差,这种情况下建议调整数据存储结构,比如扁平化嵌套的items数组

内容的提问来源于stack exchange,提问作者Yusuf Kayikci

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 23:34:56