【发布时间】: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);
})
【问题讨论】:
-
是的,将“索引”添加到“名称”字段以提高性能。请参阅链接中的“$sort + $match 序列优化”:docs.mongodb.com/manual/core/aggregation-pipeline-optimization