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

MongoDB中如何用$lookup关联嵌套数组中的歌曲详细数据?

解决MongoDB中关联艺术家、专辑与歌曲的聚合查询问题

没问题,我来帮你搞定这个嵌套关联的需求~你已经完成了艺术家和专辑的关联,要同时获取每个专辑对应的完整歌曲数据,这里有两种实用方案,取决于你的MongoDB版本:

方法一:嵌套$lookup(MongoDB 3.6+ 推荐)

这种方式不用折腾数组的展开和重组,直接在关联专辑的$lookup里嵌套另一个$lookup来关联歌曲,代码更简洁高效:

db.artists.aggregate([
  {
    $lookup: {
      from: "albums",
      localField: "albums",
      foreignField: "_id",
      as: "albums",
      // 给每个关联到的专辑单独执行关联歌曲的逻辑
      pipeline: [
        {
          $lookup: {
            from: "songs",
            localField: "songs",
            foreignField: "_id",
            as: "songs"
          }
        }
      ]
    }
  }
]).pretty()

逻辑说明:

  • 外层的$lookup先把艺术家文档里的albums(ObjectId列表)替换成完整的专辑文档数组
  • 内层的pipeline是MongoDB 3.6新增的功能,允许我们对每一条关联到的专辑文档,再执行一次小的聚合操作——这里就是用另一个$lookup把专辑里的songs(ObjectId列表)替换成完整的歌曲文档数组

方法二:$unwind + $lookup + $group(兼容旧版本MongoDB)

如果你的MongoDB版本低于3.6,没法用嵌套pipeline的话,就用「展开数组→关联歌曲→重组数组」的经典流程:

db.artists.aggregate([
  // 第一步:先关联艺术家和专辑
  {
    $lookup: {
      from: "albums",
      localField: "albums",
      foreignField: "_id",
      as: "albums"
    }
  },
  // 第二步:把专辑数组展开,让每个专辑单独成为一条文档
  { $unwind: "$albums" },
  // 第三步:给每个专辑关联对应的歌曲
  {
    $lookup: {
      from: "songs",
      localField: "albums.songs",
      foreignField: "_id",
      as: "albums.songs"
    }
  },
  // 第四步:按艺术家ID分组,把专辑重新拼成数组,同时保留艺术家的其他信息
  {
    $group: {
      _id: "$_id",
      name: { $first: "$name" },
      started_in: { $first: "$started_in" },
      active: { $first: "$active" },
      country: { $first: "$country" },
      current_members: { $first: "$current_members" },
      previous_members: { $first: "$previous_members" },
      genres: { $first: "$genres" },
      albums: { $push: "$albums" }
    }
  }
]).pretty()

步骤拆解:

  • $unwind:把艺术家文档里的albums数组拆成多条文档,每条对应一个专辑——这样我们才能针对单个专辑去关联歌曲
  • 第二个$lookup:把每个专辑里的songs ObjectId列表替换成完整的歌曲文档
  • $group:按艺术家的_id重新分组,用$push把拆分出去的专辑重新拼成数组,其他艺术家信息用$first取就行(因为同一分组里这些信息都一样)

最终效果

执行完查询后,你会得到包含完整层级数据的结果:每个艺术家下面有对应的专辑数组,每个专辑里又包含对应的完整歌曲数组,比如:

{
  "_id" : ObjectId("5b0d2b2c7ac4792df69a9942"),
  "name" : "Dream Theater",
  "started_in" : 1985,
  "active" : true,
  "country" : "US",
  "current_members" : [ ObjectId("5b0d2a7c7ac4792df69a9941") ],
  "previous_members" : [ ObjectId("5b0d2bf57ac4792df69a9954") ],
  "genres" : [ "prog metal", "prog rock" ],
  "albums" : [
    {
      "_id" : ObjectId("5b0d16ee7ac4792df69a9924"),
      "title" : "Images and words",
      "released" : ISODate("1992-07-07T00:00:00.000Z"),
      "songs" : [
        { "_id" : ObjectId("5b0d15ab7ac4792df69a9916"), "title" : "Pull me under" },
        { "_id" : ObjectId("5b0d15ee7ac4792df69a991e"), "title" : "Another day" },
        // 剩余歌曲省略
      ],
      "type" : "LP"
    },
    // 另一张专辑省略
  ]
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:04:31