node.js - MongoDB 搜索和分页聚合性能问题
问题描述
我是节点 js 和 MongoDB 的新手。我正在研究运行良好的 MongoDB 搜索和分页,但我遇到了性能问题。计数和搜索记录花费了太多时间。
如果我使用小词搜索,那么它的工作速度会更快,如果我使用“长字符串”或“数据库中没有记录”,那么它会花费太多时间,即 50 到 186.30 秒。(时间太长了,我希望它是 1 到 2 秒)。
我的记录中有超过 15,00,000 条数据。
如果我不包括搜索词的计数。它需要 0.20 到 1.5 秒,但是当我在搜索单词时计算记录时需要 25.0 到 35.0 秒。
我不知道如何减少使用搜索词计算记录的时间(查询优化)。
我尝试了最大级别的查询优化。
我也试过
{
$count: "passing_scores"
}
但没有按时更改。我坚持下去。我必须减少搜索词的计数时间。
以 SQL 查询为例
SELECT * FROM `post`
Left JOIN catagory ON post.catid=catagory.id
WHERE post_name LIKE '%a%' OR post_data LIKE '%a%' OR tags LIKE '%a%' OR post_url LIKE '%a%'
节点和 MongoDB
PostObj.count({},function(err,totalCount) {
if(err) {
response = {"error" : true,"message" : "Error fetching data"}
}
PostObj.aggregate([
{ $lookup:
{
from: 'catagories',
localField: 'catagory.catagory_id',
foreignField: '_id',
as: 'catagories_data'
}
},
{
$match:
{
$or: [
{"catagories_data.catagory_name": { $regex: new RegExp(search_data)}},
{"postname": { $regex: new RegExp(search_data) }},
{"posturl": { $regex: new RegExp(search_data) }},
{"postdata": { $regex: new RegExp(search_data) }},
{"tags": { $regex: new RegExp(search_data) }}
]
}
},
{ $limit : search_limit },
{ $skip : search_skip },
{ $group : { _id : "$_id", postname: { $push: "$postname" } , posturl: { $push: "$posturl" } } }
]).exec(function (err, data){
//end insert log data
if(err) {
response = {"error" : true,"message" :err};
}
if(search_data != "")
{
// count record using search word
PostObj.aggregate([
{ $lookup:
{
from: 'catagories',
localField: 'catagory.catagory_id',
foreignField: '_id',
as: 'catagories_data'
}
},
{
$match:
{
$or: [
{"catagories_data.catagory_name": { $regex: new RegExp(search_data)}},
{"postname": { $regex: new RegExp(search_data) }},
{"posturl": { $regex: new RegExp(search_data) }},
{"postdata": { $regex: new RegExp(search_data) }},
{"tags": { $regex: new RegExp(search_data) }}
]
}
},
{ $group: { _id: null, myCount: { $sum: 1 } } },
{ $project: { _id: 0 } }
]).exec(function (err, Countdata){
res.json({
sEcho : req.body.draw,
iTotalRecords: Countdata.myCount,
iTotalDispla,yRecords: Countdata.myCount,
aaData: data
});
}
res.json({
sEcho : req.body.draw,
iTotalRecords: totalPages,
iTotalDisplayRecords: totalPages,
aaData: data
});
});
});
此外,我必须尝试这种方式,但它比第一个代码多 35.0 到 49.0 秒。
PostObj.aggregate([
{ $lookup:
{
from: 'catagories',
localField: 'catagory.catagory_id',
foreignField: '_id',
as: 'catagories_data'
}
},
{
$match:
{
$or: [
{"catagories_data.catagory_name": { $regex: new RegExp(search_data)}},
{"postname": { $regex: new RegExp(search_data) }},
{"posturl": { $regex: new RegExp(search_data) }},
{"postdata": { $regex: new RegExp(search_data) }},
{"tags": { $regex: new RegExp(search_data) }}
]
}
},
{ '$facet' : {
metadata: [ { $count: "total" }, { $addFields: { page: NumberInt(3) } } ],
data: [ { $skip: 20 }, { $limit: 10 } ] // add projection here wish you re-shape the docs
} }
] )
如果我不使用搜索词,那效果很好。我在搜索任何单词时遇到问题(该作品的记录数没有跳过和限制)
收集数据
邮政
{
"_id": ObjectId("5d29bd7609f28633f38ccc13"),
"postname": "this is some data ",
"tags " : "
Damita,
Caro,
Leontyne,
Theodosia,
Vyky ",
"postdata ": "Berry Samara Kellia Rebekah Linette Hyacinthie Joelly Micky Tomasina Christian Fae Doralynn Chelsea Aurie Gwendolyn Tate
Cairistiona Ardys Aubrie Damita Olga Kelli Leone Marthena Kelcy
Cherlyn Molli Pris Ginelle Sula Johannah Hedwig Adelle Editha Lindsey
Loleta Lenette Ann Heidie Drona Charlena Emilia Manya Ketti Dorthea
Jeni Lorene Eolanda Karoly Loretta Marylou Tommie Leontyne Winny Cyb
Violet Pavia Karen Idelle Betty Doloritas Judye Aretha Quinta Billie
Vallie Fiona Letty Gates Shandra Rosemary Dorice Doro Coral Tove Crin
Bobbe Kristan Tierney Gianina Val Daniela Kellyann Marybeth Konstance
Nixie Andeee Jolene Patrizia Carla Arabella Berna Roseline Lira Cristy
Hedi Clem Nerissa ",
"catagory " : [
{ "catagory_id " : [ ObjectId("5d29bd7509f28633f38ccbfd")]},
{ "catagory_id": [ ObjectId("5d29bd7509f28633f38ccbfd") ]}],
"createby": "5d22f712fe481b2a9afda4aa"
}
类别
{
"_id": ObjectId("5d29bc271a68fb333531f6a1"),
"catagory_name": "Katharine",
"catagory_description": "Katharine"
}
有什么解决办法吗?
解决方案
如果在您的情况下,您的正则表达式只是在寻找一个(或几个)单词,那么最好使用$text而不是 $regex。$text 可以使用文本索引,因此速度更快。就MySQL 而言, $text 是 LIKE 并且 $regex 是 REGEXP。由于在您的示例 mysql 查询中您使用的是 LIKE,我非常有信心您也可以在您的 mongo 查询中使用 $text 而不是 $regex。
您需要(如果还没有的话)在您的字段(postname、tags、postdata 和 posturl)上有一个复合“ text ”索引。
db.POST.createIndex(
{
postname: "text",
tags: "text",
posturl: "text",
postdata: "text"
}
)
推荐阅读
- ios - 迁移到 xcframwork Xcode 12.5,dyld:未加载库
- c++ - 如何使用 NODEMCU 同时使用 MFRC522 和 RDM6300
- windows-machine-learning - 访问 TensorFloat 数据
- python - 我正在尝试使用回溯解决 N 个皇后。我的解决方案是计算值,但是返回逻辑有问题
- javascript - 尝试在单击按钮时从两个不同的文本区域复制文本
- javascript - 在烧瓶中正确执行 javasript 代码
- npm - `npm i core-js@latest` 无法安装,因为它无法构建... core-js@<3.3?
- python - 如何从值为列表的键中删除值?
- javascript - TS:如何从接口中提取键并创建类型联合
- javascript - 理智错误:必须提供“数据集”才能使用 React 执行查询