MongoDB: $in in in aggregation is slow despite the index

MongoDB: $in in aggregation is slow despite the index

我有一组用户(~8k 文档)和一组作业(~150k 文档)。我需要创建一个聚合,其中包含一个阶段,用于查找每个用户被接受的工作(在工作模型中接受的是一个 ObjectId 数组):

db.getCollection('users')
    .aggregate([
        {
            $lookup: {
                from: 'jobs',
                as: 'jobs',
                let: { accepted: '$_id' },
                pipeline: [
                    {
                        $match: {
                            $expr: {
                                $and: [
                                    { $gte: ['$timestamp', 1643223600] },
                                    { $in: ['$$accepted', '$accepted'] }
                                ]
                            }
                        },
                    },
                ]
            }
        },
    ])

这个聚合速度非常慢。即使将输出记录的数量限制为 10 个,也需要大约 1 分钟的时间才能完成。虽然,时间戳大于 1643223600 的作业数量并不是很大——大约有 3000 个文档。我添加了以下索引:

{timestamp: -1},
{accepted: 1}

但这并没有帮助。但是,如果我创建数据库的副本并删除所有不满足时间戳条件的班次,则聚合工作得更快(几秒钟)。这是否意味着该索引由于某种原因不起作用?如果 运行 对作业集合进行简单查询,并在接受字段上进行条件解释,则表明已执行 IXSCAN

UPD:由于 $in 不适用于复合索引,Mongodb4.4 的解决方法是:

 {
            $lookup: {
                from: 'jobs',
                as: 'jobs',
                localField: '_id',
                foreignField: 'accepted'
            }
        },
        { $match: { $expr: { $ne: [{ $size: '$jobs' }, 0] } } },
        { $unwind: '$jobs' },
        {
            $match: { 'jobs.timestamp': { $gte: 1643223600 } }
        },

查询
(需要 MongoDB 5)

users.aggregate(
[{"$lookup":
  {"from":"jobs",
   "localField":"_id",
   "foreignField":"accepted",
   "pipeline":[{"$match":{"timestamp":{"$gte":1643223600}}}],
   "as":"jobs"}}])

accepted 上创建多键索引后尝试此操作,如果需要,也在 timestamp 上尝试此操作。

聚合 $in 即使在 Mongodb 5 中也不能使用索引,所以它没有被使用。
请参阅 here 关于 $expr 和索引的使用。