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

如何将两个Mongoose聚合流水线合并实现特定文档筛选?

合并单聚合流水线实现方案

完全可以通过自连接($lookup)+ 聚合分组排序的方式将两个流水线合并为一个,无需单独查询namesArr。以下是具体实现:

核心逻辑

  1. 先筛选出所有满足end < x的文档(基础查询条件);
  2. 通过自连接查询每个Name是否存在符合start <= x <= end的文档;
  3. 排除掉存在上述文档的Name;
  4. 按Name分组,对组内文档按end降序排序,取第一个(即end最接近x的文档)。

聚合代码实现

假设x的值为44,对应的Mongoose聚合代码如下(注意:如果start/end是字符串类型存储的数字,需用$toInt转换后再做数值比较,否则会出现字符串比较的逻辑错误):

const x = 44;

const result = await dummy.aggregate([
  // 1. 筛选出end < x的文档
  {
    $match: {
      $expr: { $lt: [{ $toInt: "$end" }, x] }
      // 若字段本身是数字类型,可简化为:end: { $lt: x }
    }
  },
  // 2. 自连接查询当前Name是否存在符合start<=x<=end的文档
  {
    $lookup: {
      from: "dummies", // 填写集合实际名称(Mongoose默认是模型名小写复数)
      localField: "Name",
      foreignField: "Name",
      as: "has_overlap",
      pipeline: [
        {
          $match: {
            $expr: {
              $and: [
                { $lte: [{ $toInt: "$start" }, x] },
                { $gte: [{ $toInt: "$end" }, x] }
              ]
            }
          }
        }
      ]
    }
  },
  // 3. 排除存在符合条件文档的Name(has_overlap为空数组)
  {
    $match: {
      has_overlap: { $size: 0 }
    }
  },
  // 4. 按Name分组,收集组内所有文档
  {
    $group: {
      _id: "$Name",
      docs: { $push: "$$ROOT" }
    }
  },
  // 5. 组内按end降序排序,取最接近x的第一个文档
  {
    $project: {
      _id: 0,
      Name: "$_id",
      start: { $arrayElemAt: [{ $arrayElemAt: [{ $sortArray: { input: "$docs", sortBy: { end: -1 } } }, 0] }, "start"] },
      end: { $arrayElemAt: [{ $arrayElemAt: [{ $sortArray: { input: "$docs", sortBy: { end: -1 } } }, 0] }, "end"] }
    }
  }
]);

简化优化版

如果追求更高性能,可以在分组阶段直接计算每个Name的最大end,再匹配回对应文档:

const result = await dummy.aggregate([
  { $match: { $expr: { $lt: [{ $toInt: "$end" }, x] } } },
  {
    $lookup: {
      from: "dummies",
      localField: "Name",
      foreignField: "Name",
      as: "overlap_docs",
      pipeline: [
        {
          $match: {
            $expr: {
              $and: [
                { $lte: [{ $toInt: "$start" }, x] },
                { $gte: [{ $toInt: "$end" }, x] }
              ]
            }
          }
        }
      ]
    }
  },
  { $match: { overlap_docs: { $size: 0 } } },
  // 分组获取每个Name的最大end
  {
    $group: {
      _id: "$Name",
      maxEnd: { $max: { $toInt: "$end" } },
      originalDocs: { $push: "$$ROOT" }
    }
  },
  // 筛选出对应maxEnd的文档
  {
    $project: {
      _id: 0,
      Name: "$_id",
      targetDoc: {
        $first: {
          $filter: {
            input: "$originalDocs",
            cond: { $eq: [{ $toInt: "$$this.end" }, "$maxEnd"] }
          }
        }
      }
    }
  },
  // 提取最终字段
  {
    $project: {
      Name: "$Name",
      start: "$targetDoc.start",
      end: "$targetDoc.end"
    }
  }
]);

内容的提问来源于stack exchange,提问作者Mohammad AL - Haque

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 08:23:20