【问题标题】:When I search on multiple field included lookup with more then one field with $regex MongoDB perform slow当我搜索多个字段时,包含多个字段的查找 $regex MongoDB 执行速度很慢
【发布时间】:2018-06-24 17:39:21
【问题描述】:

我有书籍集合,其中包含名称、描述、出版商 ObjectID 字段、作者 ID 数组、类别 ID 字段等。我需要使用 $regex 搜索带有名称、描述、出版商名称、作者和类别名称的书籍。

为此,我首先在聚合管道中使用 $lookup 填充作者、出版商、类别,然后在字段上使用 $match 和 $or 运算符。

我的查询有效,但执行速度很慢(大约 11 秒),其中 Book 集合仅包含 70,000 个文档。

收集模型、索引或查询良好性能需要哪些步骤?

图书型号:

{
    "_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"
}

我执行的查询:

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);
    })

【问题讨论】:

标签: mongodb express mongoose


【解决方案1】:

您可以为字段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 ($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}}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2018-07-13
    • 1970-01-01
    • 1970-01-01
    • 2017-01-25
    • 1970-01-01
    相关资源
    最近更新 更多