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

MongoDB聚合$lookup中使用$regexMatch实现子串匹配关联查询

MongoDB 关联匹配消息子串的聚合实现

直接用管道模式的$lookup就能在关联阶段同时完成外键匹配和消息正文的子串过滤,避免全量关联后再过滤的性能浪费,针对给出的测试数据和需求,可直接运行的聚合代码如下:

// 待匹配的目标子串
const searchKeyword = "day";
db.patients.aggregate([
  {
    $lookup: {
      from: "messages",
      // 将当前患者文档的_id定义为关联管道内可引用的变量
      let: { patientId: "$_id" },
      pipeline: [
        {
          $match: {
            $expr: {
              $and: [
                // 关联条件:消息由当前患者创建
                { $eq: ["$createdByPatient", "$$patientId"] },
                // 子串匹配:消息正文包含目标关键词,需要忽略大小写可追加options: "i"
                { $regexMatch: { input: "$body", regex: searchKeyword } }
              ]
            }
          }
        },
        // 单患者有多条匹配消息时,取最新的1条(ObjectId自带时间戳,按_id倒序即按创建时间倒序)
        { $sort: { _id: -1 } },
        { $limit: 1 }
      ],
      as: "matchedMessages"
    }
  },
  // 过滤掉没有任何匹配消息的患者
  {
    $match: {
      "matchedMessages.0": { $exists: true }
    }
  },
  // 调整输出结构,对齐预期的lastMessage字段格式
  {
    $addFields: {
      lastMessage: { $arrayElemAt: ["$matchedMessages", 0] }
    }
  },
  // 移除中间过程生成的临时字段
  {
    $project: {
      matchedMessages: 0
    }
  }
])

关键实现说明

  • 没有使用localField/foreignField的简化$lookup写法,是因为简化写法不支持在关联时追加自定义过滤条件。通过let传参的管道式关联,可以在拉取messages表数据时直接完成双重过滤,只查询符合要求的消息,性能远高于先全量关联再过滤的写法。
  • $regexMatch是MongoDB 4.2及以上版本原生支持的聚合正则操作符,直接在管道内完成子串匹配,执行效率远高于$where类的脚本查询。
  • 关联管道内的$sort + $limit是为了适配单患者多条匹配消息的场景,直接在关联阶段取到最新的匹配消息,避免后续处理大数组的开销。如果业务需要返回患者所有匹配的消息,删掉这两个阶段,调整后续投影逻辑直接返回关联得到的消息数组即可。
  • 过滤无匹配患者时判断matchedMessages.0是否存在,比用$size计算数组长度的执行效率更高,不需要遍历整个数组。

以上述测试数据为例,传入子串day执行聚合,返回结果和预期输出完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 13:06:21