mongoose 查找我和我的朋友的数据,并使用MongoDB对其进行排序

qvk1mo1f  于 2023-06-23  发布在  Go
关注(0)|答案(1)|浏览(83)

我需要搜索有关我朋友的信息。我还想包括我的ActorId中的信息,这样在降序中,我和我的朋友都有最多的名气。
我努力构建这个查询,它没有优化。我在想办法。
friends的第一个$lookup运行得很顺利,但剩下的就有点棘手了。第二次查找user为前面$lookup的每个结果搜索请求用户(me)的信息。这样做不止一次,这是不必要的。
这里是user$lookup级。

有没有一种方法可以对管道进行分区以分离元素?我试过$group,但它不工作。
下面是我的query

const pipeline = ([
  {
    $match: {
      $or: [
        { RequesterId: ActorId },
        { ReceiverId: ActorId }
      ],
      Status: 1
    }
  },
  {
    $lookup: {
      from: "users",
      let: {
        actorId: {
          $cond: [{
            $eq: [ "$RequesterId", ActorId ]
          }, "$ReceiverId", "$RequesterId"]
        }
      },
      pipeline: [{
        $match: {
          $expr: {
            $or: [{
              $eq: [ "$$actorId", "$ActorId" ]
            }]
          }
        }
      }, {
        $addFields: {
          RoomLikes: {
            $size: "$Room.RoomActorLikes"
          }
        }
      }, {
        $project: {
          _id: 0,
          ActorId: "$ActorId",
          Name: "$Name",
          Money: "$Progression.Money",
          Fame: "$Progression.Fame",
          Fortune: "$Progression.Fortune",
          IsExtra: "$Extra.IsExtra",
          RoomLikes: "$RoomLikes"
        }
      }],
      as: "friends"
    }
  },
  {
    $lookup: {
      from: "users",
      pipeline: [{
        $match: {
          ActorId: 2
        }
      }, {
        $addFields: {
          RoomLikes: {
            $size: "$Room.RoomActorLikes"
          }
        }
      }, {
        $project: {
          _id: 0,
          ActorId: "$ActorId",
          Name: "$Name",
          Money: "$Progression.Money",
          Fame: "$Progression.Fame",
          Fortune: "$Progression.Fortune",
          IsExtra: "$Extra.IsExtra",
          RoomLikes: "$RoomLikes"
        }
      }],
      as: "user"
    }
  },
  {
    $project: {
      newArray: {
        $concatArrays: [ "$user", "$friends" ]
      }
    }
  },
  {
    $unwind: "$newArray"
  },
  {
    $replaceRoot: {
      newRoot: "$newArray",
    }
  },
  {
    $group: {
      _id: "$ActorId",
      ActorId: { $first: "$ActorId" },
      Name: { $first: "$Name" },
      Money: {$first: "$Money"  },
      Fame: { $first: "$Fame" },
      Fortune: { $first: "$Fortune" },
      IsExtra: { $first: "$IsExtra" },
      RoomLikes: { $first: "$RoomLikes" }
    }
  },
  {
    $match: {
      ActorId: { $ne: 1 }, // Remove MSPRetro account from the result
      IsExtra: 0 // Remove deleted users from the result
    }
  },
  { $sort: { Fame: -1 } },
  { $skip: request.pageindex * 7 },
  { $limit: 7 }
]);

提前感谢您的帮助!

mftmpeh8

mftmpeh81#

你需要the $unionWith stage,沿着如下:

db.friends.aggregate([
  {
    "$match": {
      "$or": [
        {
          "RequesterId": 2
        },
        {
          "ReceiverId": 2
        }
      ],
      "Status": 1
    }
  },
  {
    "$lookup": {
      "from": "users",
      "let": {
        "actorId": {
          "$cond": [
            {
              "$eq": [
                "$RequesterId",
                2
              ]
            },
            "$ReceiverId",
            "$RequesterId"
          ]
        }
      },
      "pipeline": [
        {
          "$match": {
            "$expr": {
              "$or": [
                {
                  "$eq": [
                    "$$actorId",
                    "$ActorId"
                  ]
                }
              ]
            }
          }
        }
      ],
      "as": "friends"
    }
  },
  {
    "$unwind": "$friends"
  },
  {
    "$replaceRoot": {
      "newRoot": "$friends"
    }
  },
  {
    "$unionWith": {
      coll: "users",
      "pipeline": [
        {
          "$match": {
            "ActorId": 2
          }
        }
      ]
    }
  },
  {
    "$match": {
      "ActorId": {
        "$ne": 1
      },
      "Extra.IsExtra": 0
    }
  },
  {
    "$sort": {
      "Fame": -1
    }
  },
  {
    "$skip": 0
  },
  {
    "$limit": 7
  },
  {
    "$project": {
      "_id": 0,
      "ActorId": "$ActorId",
      "Name": "$Name",
      "Money": "$Progression.Money",
      "Fame": "$Progression.Fame",
      "Fortune": "$Progression.Fortune",
      "IsExtra": "$Extra.IsExtra",
      "RoomLikes": {
        "$size": "$Room.RoomActorLikes"
      }
    }
  }
])

Demo playground
我还修改了一些其他的东西,特别是:

  • 摆脱了$addFields阶段,因为该逻辑可以直接发生在$project中。
  • 将两个$project合并为一个,并将其移动到管道的最后一级。
  • 更新了$match中的"Extra.IsExtra"字段名称,因为我将其拉到$project之前。
  • 摆脱$group(我认为它只存在于最初的双$lookup方法中。这将删除一个阻塞阶段,但对于$sort,您仍然有另一个阻塞阶段。

我个人也希望在管道中更早地包含$match逻辑(例如直接在$lookup$unionWith中),但我不知道这些数据是否有很大的区别。

相关问题