mongoose 当我搜索包含多个字段的查找时,使用$regex MongoDB查找多个字段执行速度很慢

nlejzf6q  于 2023-03-12  发布在  Go
关注(0)|答案(1)|浏览(98)

我有书的名称,描述,出版商ObjectID字段,作者ID数组,类别ID字段等收集我需要搜索名称,描述,出版商名称,作者和$regex类别名称的书。
要在聚合管道中实现这一点,我首先使用$lookup填充authors、publisher、categories,然后在字段上使用带有$or运算符的$match。
我的查询工作,但它执行非常缓慢(约11秒),其中图书收集只包含7万个文档。
在集合模型、索引或查询中需要哪些步骤才能获得良好的性能?
书本型号:

{
    "_id" : ObjectId("5a2934934410bf8b0e547989"),
    "publisher" : ObjectId("5a27e7b68021772210b125d4"),
    "is_enabled" : true,
    "published_at" : ISODate("2017-12-07T12:31:15.166Z"),
    "author" : [ 
        ObjectId("5a27c5754b0efc477f37a131"),
        ObjectId("5a27c5754b0efc47737a1512"),
        ObjectId("5a27c5754b0efc477f37a145"),
    ],
    "category" : [ 
        ObjectId("5a27e22ffb6110b11c326cd7"), 
        ObjectId("5a27e22ffb6110b11c326ced"), 
        ObjectId("5a27e22ffb6110b11c326d2d"), 
        ObjectId("5a27e22ffb6110b11c326e45")
    ]
    "published_year" : "2017"
}

质询I执行:

Book.aggregate(
    [
        {
            $match: {
                "is_enabled": { $eq: true },
            }
        },
        {
            $lookup:
                {
                    from: "authors",
                    localField: "author",
                    foreignField: "_id",
                    as: "author"
                }
        },
        {
            $lookup:
                {
                    from: "categories",
                    localField: "category",
                    foreignField: "_id",
                    as: "category"
                }
        },
        {
            $lookup:
                {
                    from: "publishers",
                    localField: "publisher",
                    foreignField: "_id",
                    as: "publisher"
                }
        },
        {
            $match: {
                $or: [
                    { "author.name": new RegExp(params.expression, 'i') },
                    { "category.name": new RegExp(params.expression, 'i') },
                    { "publisher.name": new RegExp(params.expression, 'i') },
                    { "description": new RegExp(params.expression, 'i') },
                    { "name": new RegExp(params.expression, 'i') },
                    { "published_year": params.terms }
                ]
            }
        },
        {
            $project: {
                previous_price: "$previous_price",
                price: "$price",
                name: "$name",
                seo_url: "$seo_url",
                click_url: "book",
                author: "$author",
                authorObj: {
                    name: { $arrayElemAt: ["$author.name", 0] },
                }
            }
        },
        { $sort: { name: 1 } }
    ]
)
    .skip(8 * (params.pagenum - 1))
    .limit(8)
    .exec((err, product) => {
        if (err)
            reject(err);
        else
            resolve(product);
    })
jdgnovmf

jdgnovmf1#

您可以为字段is_enabled, author, category and publisher创建索引,如下所示。

db.coll.createIndex( { is_enabled: 1 } )
db.coll.createIndex( { author: 1 } )
db.coll.createIndex( { category: 1 } )
db.coll.createIndex( { publisher: 1 } )

这将提高第一匹配阶段和查找的性能。
您也可以为name, description and published_year创建索引,但我不确定该索引对最后匹配阶段的影响,因为您使用了$or条件。据我所知,仍然无法优化使用$or, $in的索引查询(〈=3.2)。您可以尝试一下。如果您使用$and条件查询,这会很有帮助。如果您使用$and查询,则还可以创建***多键索引***对于name, description and published_year。类似

db.coll.createIndex( { name: 1, description: 1 published_year:1 } )

然后在匹配条件中遵循相同的顺序

{$match: { name: 'xx', description:'yy', published_year: 2017}}

相关问题