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

如何基于字段值在MongoDB中关联不同集合执行Lookup查询

动态关联不同集合填充数组元素数据

问题场景

现有MongoDB文档结构如下:

{
   name: 'my list',
   items: [
      { type: 'book', id: 5364 },
      { type: 'car', id: 354 },
      { type: 'laptop', id: 228 }
   ]
}

对应的Mongoose Schema定义:

{
   name: String,
   items: {
      type: Array,
      default: []
   }
}

需要根据items数组中每个元素的type字段,从对应的集合(如books、cars、laptops)中获取对应id的文档,最终输出结构如下:

{
   name: 'my list',
   items: [
      { type: 'book', id: 5364, data: [{...}] },
      { type: 'car', id: 354, data: [{...}] },
      { type: 'laptop', id: 228, data: [{...}] }
   ]
}

解决方案

方法一:聚合管道实现(高性能推荐)

利用MongoDB聚合管道的$map、$switch和$lookup组合,实现动态关联不同集合:

const result = await YourListModel.aggregate([
  // 可选:匹配目标文档,根据业务需求添加过滤条件
  { $match: { name: 'my list' } },
  // 遍历items数组,根据type关联对应集合
  {
    $addFields: {
      items: {
        $map: {
          input: '$items',
          as: 'item',
          in: {
            type: '$$item.type',
            id: '$$item.id',
            data: {
              $switch: {
                branches: [
                  {
                    case: { $eq: ['$$item.type', 'book'] },
                    then: {
                      $lookup: {
                        from: 'books',
                        localField: '$$item.id',
                        foreignField: '_id',
                        as: 'bookData'
                      }
                    }
                  },
                  {
                    case: { $eq: ['$$item.type', 'car'] },
                    then: {
                      $lookup: {
                        from: 'cars',
                        localField: '$$item.id',
                        foreignField: '_id',
                        as: 'carData'
                      }
                    }
                  },
                  {
                    case: { $eq: ['$$item.type', 'laptop'] },
                    then: {
                      $lookup: {
                        from: 'laptops',
                        localField: '$$item.id',
                        foreignField: '_id',
                        as: 'laptopData'
                      }
                    }
                  }
                ],
                default: []
              }
            }
          }
        }
      }
    }
  },
  // 整理data字段,提取对应集合的查询结果
  {
    $addFields: {
      items: {
        $map: {
          input: '$items',
          as: 'item',
          in: {
            type: '$$item.type',
            id: '$$item.id',
            data: {
              $arrayElemAt: [
                {
                  $switch: {
                    branches: [
                      { case: { $eq: ['$$item.type', 'book'] }, then: '$$item.data.bookData' },
                      { case: { $eq: ['$$item.type', 'car'] }, then: '$$item.data.carData' },
                      { case: { $eq: ['$$item.type', 'laptop'] }, then: '$$item.data.laptopData' }
                    ],
                    default: []
                  }
                },
                0 // 若查询单条文档,取出数组第一个元素;多条则直接保留数组
              ]
            }
          }
        }
      }
    }
  }
]);

方法二:手动遍历查询(逻辑直观)

先获取主文档,再遍历items数组逐个查询对应集合数据:

const listDoc = await YourListModel.findOne({ name: 'my list' });
if (!listDoc) return;

// 并行查询所有关联数据
listDoc.items = await Promise.all(
  listDoc.items.map(async (item) => {
    let data = [];
    // 根据type匹配对应模型查询
    switch (item.type) {
      case 'book':
        data = await BookModel.find({ _id: item.id });
        break;
      case 'car':
        data = await CarModel.find({ _id: item.id });
        break;
      case 'laptop':
        data = await LaptopModel.find({ _id: item.id });
        break;
      default:
        data = [];
    }
    return { ...item, data };
  })
);

// 此时listDoc即为期望结构
console.log(listDoc);

注意事项

  • 确保item.id与对应集合_id的类型一致(如均为ObjectId或数字),类型不匹配时需转换(例如用mongoose.Types.ObjectId(item.id))。
  • 聚合管道方法适合大数据量场景,性能更优;手动查询逻辑简单,适合小数据量或快速开发场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 22:10:30