MongoDB multiple/nested 聚合

MongoDB multiple/nested aggregations

我有这些 collections:

users

{
  _id: "userId1",
  // ...
  tracks: ["trackId1", "trackId2"],
};

tracks

{
  _id: "trackId1",
  // ...
  creatorId: "userId1",
  categoryId: "categoryId1"
}

categories

{
  _id: "categoryId1",
  // ...
  tracks: ["trackId1", "trackId15", "trackId20"],
};

通过使用以下代码,我可以通过 ID 获取曲目并添加创作者

tracks.aggregate([
        {
          $match: { _id: ObjectId(trackId) },
        },
        {
          $lookup: {
            let: { userId: { $toObjectId: "$creatorId" } },
            from: "users",
            pipeline: [{ $match: { $expr: { $eq: ["$_id", "$$userId"] } } }],
            as: "creator",
          },
        },
        { $limit: 1 },
      ])
      .toArray();

回复:

"track": {
    "_id": "trackId1",
    // ...
    "categoryId": "categoryId1",
    "creatorId": "userId1",
    "creator": {
        "_id": "userId1",
        // ...
        "tracks": [
            "trackId5",
            "trackId10",
            "trackId65"
        ]
    }
}

但我正在苦苦挣扎的是我希望 creator.tracks 聚合也通过它们的 ID 返回曲目(例如,最多最后 5 个),并从 [= 中获取最后 5 个曲目22=]

预期结果:

"track": {
    "_id": "trackId1",
    // ...
    "categoryId": "categoryId1",
    "creatorId": "userId1",
    "creator": {
        "_id": "userId1",
        "tracks": [
            {
                "_id": "trackId5",
                // the rest object without the creator
            },
            {
                "_id": "trackId10",
                // the rest object without the creator
            },
            {
                "_id": "trackId65",
                // the rest object without the creator
            },
        ]
    },
    // without trackId1 which is the one that is being viewed
    "relatedTracks": [
        {
            "_id": "trackId15",
            // the rest object without the creator
        },
        {
            "_id": "trackId20",
            // the rest object without the creator
        },
    ]
}

我将不胜感激 explanation/help 了解什么是最好的做法并且仍然保持良好的性能

查询

  • 从曲目开始
  • 使用 trackId 加入用户获取创作者的所有曲目 (创作者曲目)
  • 使用 categoryId 加入类别以获取该类别的所有曲目(相关曲目)
  • 从相关曲目中删除创作者的曲目
  • 使用 $slice(创作者曲目和相关曲目)从两者中取最后 5 个

*我添加了 2 个额外的查找来获取轨道的所有信息,它的空数组是因为我没有足够的数据(我只有 trackId1),所有数据都可以工作

PlayMongo

db.tracks.aggregate([
  {
    "$match": {
      "_id": "trackId1"
    }
  },
  {
    "$lookup": {
      "from": "users",
      "localField": "creatorId",
      "foreignField": "_id",
      "as": "creator-tracks"
    }
  },
  {
    "$set": {
      "creator-tracks": {
        "$arrayElemAt": [
          "$creator-tracks.tracks",
          0
        ]
      }
    }
  },
  {
    "$lookup": {
      "from": "categories",
      "localField": "categoryId",
      "foreignField": "_id",
      "as": "related-tracks"
    }
  },
  {
    "$set": {
      "related-tracks": {
        "$arrayElemAt": [
          "$related-tracks.tracks",
          0
        ]
      }
    }
  },
  {
    "$set": {
      "related-tracks": {
        "$filter": {
          "input": "$related-tracks",
          "cond": {
            "$not": [
              {
                "$in": [
                  "$$this",
                  "$creator-tracks"
                ]
              }
            ]
          }
        }
      }
    }
  },
  {
    "$set": {
      "creator-tracks": {
        "$slice": [
          {
            "$filter": {
              "input": "$creator-tracks",
              "cond": {
                "$ne": [
                  "$$this",
                  "$_id"
                ]
              }
            }
          },
          -5
        ]
      }
    }
  },
  {
    "$set": {
      "related-tracks": {
        "$slice": [
          "$related-tracks",
          -5
        ]
      }
    }
  },
  {
    "$lookup": {
      "from": "tracks",
      "localField": "creator-tracks",
      "foreignField": "_id",
      "as": "creator-tracks-all-info"
    }
  },
  {
    "$lookup": {
      "from": "tracks",
      "localField": "related-tracks",
      "foreignField": "_id",
      "as": "related-tracks-all-info"
    }
  }
])