将 MongoDB 聚合 $lookup 限制为仅 1 个匹配项

Mic*_*ael 5 mongodb aggregation-framework

有两个集合,usersreports

我的目标是进行聚合以获取所有用户,并且每个用户都user包含用户的最后一个 report.

这是我目前的聚合:

db.users.aggregate([{
  $lookup: {
    from: 'reports',
    localField: '_id',
    foreignField: 'userId',
    as: 'report',
  },
}, {
  $project: {
    'lastReportAmount': {
      $let: {
        vars: {
          lastReport: {'$arrayElemAt': ['$report', 0]},
        },
        in: '$$lastReport.amount',
      },
    },
    'id': '$_id',
    'name': 1,
    'firstLogin': 1,
    'email': 1,
  },
}])
Run Code Online (Sandbox Code Playgroud)

此查询工作正常,但速度很慢。
这样做的原因是$lookup返回与某个匹配的所有报告userId,而不是一个(最后一个)。

有没有办法限制$lookup只有一场比赛?

use*_*814 5

您可以尝试 3.6 中提供的新查找变体。

在报告集合中的 userId 和 date 字段上添加一个索引,看看它是否被选中。

db.users.aggregate([
 {"$lookup":{
    "from": "reports",
    "let": {"_id":"$_id"},
    "pipeline":[
      {"$match":{"$expr":{"$eq":["$$_id","$userId"]}}},
      {"$sort":{"date": -1}},
      {"$limit":1}
    ],
    "as": "lookup-latest"
 }},
 {"$project": {
    'lastReportAmount':{'$arrayElemAt':['$lookup-latest', 0]},
    'id': '$_id',
    'name': 1,
    'firstLogin': 1,
    'email': 1
 }}
])
Run Code Online (Sandbox Code Playgroud)