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

如何编写MongoDB聚合查询筛选匹配系统的合适会话?

MongoDB聚合查询实现匹配系统需求

需求描述

用户"TARGET"发起匹配请求,需通过MongoDB聚合查询完成以下逻辑:

  • 从sessions集合中筛选出所有type: "TEXT"且status: "WAITING"的会话文档
  • 对每个筛选出的文档,检查该文档members[0]对应的用户与"TARGET"是否在集合内任意文档的members数组中共同出现过(即是否有过匹配记录)
  • 排除曾匹配过的会话,返回最终符合条件的会话列表

示例数据

sessions集合的示例文档如下:

[
    {
        "status": "WAITING",
        "type": "TEXT",
        "members": [ "adam" ]
    },
    {
        "status": "WAITING",
        "type": "TEXT",
        "members": [ "john" ]
    },
    {
        "status": "WAITING",
        "type": "VOICE",
        "members": [ "alex" ]
    },
    {
        "status": "ENDED",
        "type": "VOICE",
        "members": [ "adam", "alex" ]
    },
    {
        "status": "TIMEOUT",
        "type": "TEXT",
        "members": [ "adam", "TARGET" ]
    }
]

期望返回结果

[
    {
        "status": "WAITING",
        "type": "TEXT",
        "members": [ "john" ]
    }
]

结果说明

集合中共有3个WAITING状态的会话:

  • adam的会话:TARGET曾与adam在TIMEOUT状态的会话中匹配过,因此排除
  • alex的会话:类型为VOICE,不符合TEXT类型要求,因此排除
  • john的会话:既符合类型和状态要求,且与TARGET无匹配记录,因此保留

聚合查询实现

以下是满足需求的MongoDB聚合管道:

db.sessions.aggregate([
    // 第一步:筛选出TEXT类型、WAITING状态的会话
    {
        $match: {
            type: "TEXT",
            status: "WAITING"
        }
    },
    // 第二步:为每个候选会话关联所有包含TARGET的会话,检查是否与当前用户有共同匹配记录
    {
        $lookup: {
            from: "sessions",
            let: { candidateUser: { $arrayElemAt: ["$members", 0] } },
            pipeline: [
                {
                    $match: {
                        $expr: {
                            $and: [
                                { $in: ["TARGET", "$members"] },
                                { $in: ["$$candidateUser", "$members"] }
                            ]
                        }
                    }
                }
            ],
            as: "matchedHistory"
        }
    },
    // 第三步:排除有匹配历史的会话(matchedHistory为空数组表示无匹配记录)
    {
        $match: {
            matchedHistory: { $size: 0 }
        }
    },
    // 第四步:移除临时字段matchedHistory,保留原会话结构
    {
        $project: {
            matchedHistory: 0
        }
    }
])

管道逻辑说明

  1. $match:先过滤出符合基础条件的等待会话
  2. $lookup:针对每个候选会话的用户,查询集合中同时包含该用户和TARGET的所有会话,将结果存入matchedHistory数组
  3. $match:只保留matchedHistory为空的会话(即无匹配记录)
  4. $project:移除查询过程中生成的临时字段,返回原始会话结构

参考JS代码

原需求的JS实现逻辑(供对照参考):

let waiting = findSessions()  // 常规查询获取status为"WAITING"的会话
let results = [];
for (let w of waiting) {
    // 仅当w.members[0]与TARGET_USER_ID从未匹配过时,才加入结果
    // 即集合中不存在同时包含这两个ID的文档
    if (!hasMatchedBefore(w.members[0], "TARGET_USER_ID")) {
        results.push(w);
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 02:25:16