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

MongoDB:无需$lookup匹配嵌套文档数组与对应值的方法

问题描述

我的文档结构如下:

{
    ...
    problems:
        [ { ... id: 1, ...}, { ... id: 7, ...}, { ... id: 122, ...} ],
    solutions:
        [ { ... assignedProblems: [1, 7] ... }, { ... assignedProblems: [122] ...} ],
    ... 
}

需要将solutions中的assignedProblems数组,与同文档内problems数组的id进行匹配关联。

当前使用的聚合操作虽然能正常运行,但即使添加索引后性能依然极差:

{
    $unwind: {
        path: "$solutions"
    },
    $lookup: {
        from: "problems",
        localField: "solutions.assignedProblems",
        foreignField: "id",
        as: "problems"
    }
}

曾尝试用$match替代$lookup,但$setEquals和$eq仅在两边数组元素数量完全一致时生效:

$match: {
    $expr: {
        $setEquals: ["$solutions.assignedProblems", "$problems.id"]
    }
 }

请问有没有其他方法可以实现这种id数组与内部文档数组的匹配,避免低效的$lookup?

解决方案

可以利用MongoDB的数组操作符在单文档内完成匹配,无需跨集合的$lookup,具体步骤如下:

  1. 先用$unwind拆分solutions数组,逐个处理每个solution项
  2. 使用$filter从当前文档的problems数组中,筛选出id存在于assignedProblems中的元素

完整聚合示例:

[
    { $unwind: "$solutions" },
    {
        $addFields: {
            "solutions.matchedProblems": {
                $filter: {
                    input: "$problems",
                    cond: { $in: ["$$this.id", "$solutions.assignedProblems"] }
                }
            }
        }
    },
    // 可选步骤:如果需要将solutions重新组合为数组,添加以下$group操作
    {
        $group: {
            _id: "$_id",
            problems: { $first: "$problems" },
            solutions: { $push: "$solutions" },
            // 保留其他需要的字段,根据字段类型选择$first或对应操作符
            otherField: { $first: "$otherField" }
        }
    }
]

关键说明

  • $filter完全在单文档内处理数据,不会产生跨集合查询的开销,性能远优于$lookup
  • 如果不需要保留solutions的数组结构,可以跳过最后的$group步骤
  • 无需额外创建索引,仅依赖单文档内的数组遍历匹配

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 13:42:21