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

MongoDB如何基于特定字段值实现$lookup关联查询

MongoDB 单次聚合实现优先级关联查询

我是MongoDB新手,现在有个需求:现有两个集合Collection1和Collection2,结构如下:

Collection1 结构

[
    {
        "id": "1a5086e1-c9ce-4c65-a4b3-u753hd7278",
        "entityId": "https://sxy.co",
        "providedBy": "text value",
        "type": "Display",
        "exhibitCreatedDate": "2023-01-13T09:27:04.000561Z",
        "effectiveDate": "2020",
        "link_id": "1a5086e1-c9ce-4c65-a4b3-yE46734g6j891"
    },
    {
        "id": "1a5086e1-c9ce-4c65-oa4b3-u753djf7278",
        "entityId": "https://sijh.co",
        "providedBy": "text value",
        "type": "Actual",
        "exhibitCreatedDate": "2023-01-13T09:27:04.000561Z",
        "effectiveDate": "2020",
        "link_id": "1a5086e1-c9ce-4c65-a4b3-yE46734g6j891"
    }
]

Collection2 结构

[
    {
        "_id": "1a5086e1-c9ce-4c65-a4b3-yE46734g6j891",
        "telephoneNumber": "+44-20-7424-4200",
        "faxNumber": "+44-20-7483-2293",
        "createdDate": "2023-01-13T09:27:04.000255Z",
        "modifiedDate": "2023-01-13T09:27:04.000255Z"
    },
    {
        "_id": "1a5086e1-c9ce-4c65-oa4b3-u753djf7278",
        "type": "test value",
        "telephoneNumber": "+44-20-7424-4200",
        "faxNumber": "+44-20-7483-2293",
        "createdDate": "2023-01-13T09:27:04.000255Z",
        "modifiedDate": "2023-01-13T09:27:04.000255Z"
    }
]

需求是基于link_id和_id字段执行$lookup关联,规则为:优先对Collection1中type为"Display"的文档执行关联;如果没有这类文档,再对type为"Actual"的文档执行关联。目前我用两次聚合查询实现这个逻辑,能不能合并成单次查询?

当前的两次查询代码:

// 查询Display类型文档并关联
db.Collection1.aggregate([
    {
        $match: { type: "Display" }
    },
    {
        $lookup: {
            from: "Collection2",
            localField: "link_id",
            foreignField: "_id",
            as: "Detail"
        }
    },
    { $sort: { exhibitCreatedDate: -1 } }
]).pretty();

// 查询Actual类型文档并关联
db.Collection1.aggregate([
    {
        $match: { type: "Actual" }
    },
    {
        $lookup: {
            from: "Collection2",
            localField: "link_id",
            foreignField: "_id",
            as: "Detail"
        }
    },
    { $sort: { exhibitCreatedDate: -1 } }
]).pretty();

解决方案:单次聚合查询实现

可以通过聚合的多阶段组合实现这个逻辑,核心思路是先按link_id分组,优先保留type为"Display"的文档,再执行关联操作。完整代码如下:

db.Collection1.aggregate([
    // 筛选出符合条件的类型(Display或Actual)
    {
        $match: {
            $or: [
                { type: "Display" },
                { type: "Actual" }
            ]
        }
    },
    // 给文档设置优先级,Display优先级高于Actual
    {
        $addFields: {
            priority: {
                $cond: { if: { $eq: ["$type", "Display"] }, then: 1, else: 2 }
            }
        }
    },
    // 按link_id分组,每组只保留优先级最高的文档(优先Display)
    {
        $group: {
            _id: "$link_id",
            doc: { $first: "$$ROOT" }
        }
    },
    // 恢复文档的根结构
    {
        $replaceRoot: { newRoot: "$doc" }
    },
    // 关联Collection2集合
    {
        $lookup: {
            from: "Collection2",
            localField: "link_id",
            foreignField: "_id",
            as: "Detail"
        }
    },
    // 按创建日期倒序排序
    {
        $sort: { exhibitCreatedDate: -1 }
    },
    // 移除优先级字段(可选)
    {
        $project: { priority: 0 }
    }
]).pretty();

逻辑说明:

  • $match:过滤出仅包含Display和Actual类型的文档,减少后续处理的数据量。
  • $addFields:为文档添加优先级标识,Display设为1(更高优先级),Actual设为2。
  • $group:按link_id分组,用$first保留每组中优先级最高的文档——如果同一link_id下既有Display又有Actual,只会保留Display;如果只有Actual,则保留Actual。
  • $replaceRoot:将分组后的文档恢复为根结构,方便后续关联操作。
  • $lookup:执行关联查询,拉取Collection2中的对应数据。
  • $sort:保持和原查询一致的倒序排序逻辑。
  • $project:可选步骤,移除临时添加的优先级字段,让返回结果更整洁。

这样就能通过单次聚合查询实现你需要的优先级关联逻辑,无需分两次查询。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 00:44:57