请问这个mongodb聚合查询如何优化?

聚合查询如下

db.fridge.aggregate(聚合查询语句)

聚合查询语句

[
        {
            $lookup: {
                from: 'samplelabels',
                localField: 'sample_name',
                foreignField: 'sample_name',
                as: 'sample_labels'
            }
        },
        {
            $lookup: {
                from: 'samples',
                localField: 'sample_name',
                foreignField: 'name',
                as: 'sample_detail'
            }
        },
        {
            $match: q
        },
        {
            $unwind: '$sample_detail'
        },
    ]

其中match的条件有可能如下:

{
    fid: xxx, //fridge表查询条件
    fxxx: xxx, // fridge表其他条件
    sample_labels.label_name: xxx, // samplelabels表条件
    sample_detail.viallabel: xxx, // samples表条件
}

我试过给samplelabels.label_name和samples.viallabel加索引, 但explain下来还是全表搜索.
请问该如何优化?

阅读 2k
1 个回答

对于查询条件中的 fridge 表,你可以尝试为 fid 和 fxxx 字段创建索引,以加快匹配速度。对于 samplelabels 表和 samples 表,可以尝试将聚合查询中的 $match 阶段放到 $lookup 的 pipeline 中,并在 pipeline 中为查询条件字段添加索引。这样可以将匹配过滤提前到 $lookup 阶段进行,从而减小聚合查询的数据量。

例如,修改聚合查询语句为:

[
    {
        $lookup: {
            from: 'samplelabels',
            let: { sample_name: '$sample_name', label_name: 'xxx' }, // 通过let声明变量
            pipeline: [
                { $match: { $expr: { $and: [ { $eq: ['$sample_name', '$$sample_name'] }, { $eq: ['$label_name', '$$label_name'] } ] } } }, // 在pipeline中使用let声明的变量进行匹配
                { $limit: 1 } // 可选,如果只需要匹配一个文档
            ],
            as: 'sample_labels'
        }
    },
    {
        $lookup: {
            from: 'samples',
            let: { sample_name: '$sample_name', viallabel: 'xxx' },
            pipeline: [
                { $match: { $expr: { $and: [ { $eq: ['$name', '$$sample_name'] }, { $eq: ['$viallabel', '$$viallabel'] } ] } } },
                { $limit: 1 }
            ],
            as: 'sample_detail'
        }
    },
    {
        $match: {
            $and: [
                { fid: xxx },
                { fxxx: xxx },
                { 'sample_labels.label_name': xxx },
                { 'sample_detail.viallabel': xxx }
            ]
        }
    },
    {
        $unwind: '$sample_detail'
    }
]

其中,$match 阶段中的条件使用 $and 连接起来,同时在 $lookup 中使用 let 声明变量,在 $match 的 pipeline 中使用这些变量进行匹配,从而加速过滤操作。需要注意的是,在 $lookup 的 pipeline 中使用了 $limit: 1,这是因为只需要匹配一个文档即可,可以减小查询量,提高查询效率。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏