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

如何用Node.js MongoDB驱动合并多集合并筛选含视频的媒体条目

多集合并联筛选实现方案

针对跨集合合并的需求,使用MongoDB 4.3.1及以上版本支持的$unionWith聚合阶段实现,无需多次查询后在应用层合并,可直接在数据库层面完成去重、字段整理和合并操作。

整体处理逻辑

  • 拆分4个独立预处理分支,分别处理不同来源的符合条件数据
  • 统一通过$filter提取media_urls中的视频链接,避免直接$unwind拆分数组产生重复
  • 每个分支预处理完成后再通过$unionWith合并,输出结构统一不会混乱

各分支处理规则

  1. Business嵌套商品分支(type=products)
    • 先对Business集合的products数组执行$unwind,拆分每个商品为独立条目
    • 用正则匹配商品的media_urls中是否存在视频文件
    • 保留商品自身的_id、name、lower_price、higher_price、description字段,标注type为products
    • 用$filter过滤出media_urls中的视频链接
  2. Business主体媒体分支(type=business)
    • 直接匹配Business集合自身的media_urls中是否存在视频文件
    • 仅保留Business的_id字段,标注type为business
    • 用$filter过滤出自身media_urls中的视频链接
  3. Offer集合分支(type=offer)
    • 匹配Offer集合自身media_urls含视频的条目
    • 保留Offer的_id、name、lower_price、higher_price、description字段,标注type为offer
    • 用$filter过滤出media_urls中的视频链接
  4. Product Request集合分支(type=request)
    • 匹配Product Request集合自身media_urls含视频的条目
    • 保留Request的_id、name、lower_price、higher_price、description字段,标注type为request
    • 用$filter过滤出media_urls中的视频链接

完整聚合示例代码

// 先处理Business集合的两个分支,再依次合并其他集合
db.Business.aggregate([
  // 第一阶段:先处理Business嵌套的商品条目
  {
    $unwind: "$products"
  },
  // 筛选商品媒体含视频的条目
  {
    $match: {
      "products.media_urls": { $regex: /\.(mp4|mov|avi)$/i }
    }
  },
  // 整理为统一输出结构
  {
    $project: {
      _id: "$products._id",
      type: { $literal: "products" },
      name: "$products.name",
      lower_price: "$products.lower_price",
      higher_price: "$products.higher_price",
      description: "$products.description",
      // 仅保留视频链接
      media_urls: {
        $filter: {
          input: "$products.media_urls",
          as: "url",
          cond: { $regexMatch: { input: "$$url", regex: /\.(mp4|mov|avi)$/i } }
        }
      }
    }
  },
  // 合并Business主体媒体的处理结果
  {
    $unionWith: {
      coll: "Business",
      pipeline: [
        // 筛选Business自身媒体含视频的条目
        { $match: { media_urls: { $regex: /\.(mp4|mov|avi)$/i } } },
        {
          $project: {
            _id: 1,
            type: { $literal: "business" },
            media_urls: {
              $filter: {
                input: "$media_urls",
                as: "url",
                cond: { $regexMatch: { input: "$$url", regex: /\.(mp4|mov|avi)$/i } }
              }
            }
          }
        }
      ]
    }
  },
  // 合并Offer集合的处理结果
  {
    $unionWith: {
      coll: "Offer",
      pipeline: [
        { $match: { media_urls: { $regex: /\.(mp4|mov|avi)$/i } } },
        {
          $project: {
            _id: 1,
            type: { $literal: "offer" },
            name: 1,
            lower_price: 1,
            higher_price: 1,
            description: 1,
            media_urls: {
              $filter: {
                input: "$media_urls",
                as: "url",
                cond: { $regexMatch: { input: "$$url", regex: /\.(mp4|mov|avi)$/i } }
              }
            }
          }
        }
      ]
    }
  },
  // 合并Product Request集合的处理结果
  {
    $unionWith: {
      coll: "Product Request",
      pipeline: [
        { $match: { media_urls: { $regex: /\.(mp4|mov|avi)$/i } } },
        {
          $project: {
            _id: 1,
            type: { $literal: "request" },
            name: 1,
            lower_price: 1,
            higher_price: 1,
            description: 1,
            media_urls: {
              $filter: {
                input: "$media_urls",
                as: "url",
                cond: { $regexMatch: { input: "$$url", regex: /\.(mp4|mov|avi)$/i } }
              }
            }
          }
        }
      ]
    }
  }
])

注意事项

  • 本方案中的$unwind仅用于拆分Business集合嵌套的products数组,不会拆分media_urls字段,所有视频链接会统一保留在同一条结果的数组中,不会产生重复条目
  • 正则规则可根据实际业务的视频后缀调整,无需额外匹配图片格式
  • 若需要对合并后的结果按type或其他字段排序,可在最后追加$sort阶段
  • 若MongoDB版本低于4.3.1,可先分别对3个集合执行独立聚合查询,在应用层手动合并结果,注意提前对嵌套数组做$filter处理避免重复数据

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.22 15:24:00