我是Node 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%'
NODE和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”:“这是 一些数据”,“标签”:“ Damita,Caro,Leontyne,Theodosia,Vyky”,“ postdata” :“贝瑞·萨马拉·凯莉·丽贝卡·琳妮特·莱恩·凯西·乔利·米基 Tomasina Christian Fae Doralynn切尔西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艾米莉亚·曼雅·凯蒂·多西娅 珍妮·洛琳(Jeni Lorene)Eolanda Karoly洛雷塔(Loretta)Marylou Tommie Leontyne Winny Cyb 紫罗兰色Pavia卡伦·艾黛尔·贝蒂·多洛里塔斯·朱迪·艾丽莎·昆塔·比利 瓦莱·菲奥娜·莱蒂·盖茨Shandra Rosemary Dorice Doro Coral Tove Crin Bobbe Kristan Tierney Gianina Val Daniela Kellyann Marybeth Konstance 尼克·安迪(Jinene Andeee)珍妮(Jolene Patrizia) Hedi Clem Nerissa“,” catagory“:[{” catagory_id“:[ ObjectId(“ 5d29bd7509f28633f38ccbfd”)]},{“ catagory_id”:[ ObjectId(“ 5d29bd7509f28633f38ccbfd”)]}],“ createby”: “ 5d22f712fe481b2a9afda4aa”} ..........
类别
{“ _id”:ObjectId(“ 5d29bc271a68fb333531f6a1”),“ catagory_name”: “ Katharine”,“ catagory_description”:“ Katharine”} ..........
有什么解决办法吗?
答案 0 :(得分:0)
我可以建议您尝试一些技巧。
1:POST
个收藏夹
似乎您在category_id
对象属性数组中仅存储category
,应避免使用。
相反,您应该做的如下。
在[{1}}集合中创建新属性post_id
,而不是[高性能方法]中category
中类别对象的数组。
OR
将帖子收集形式的对象的post collection
属性转换为简单数组。 [平均效果]。
category
在两种情况下都必须对
Ex: category: [ ObjectId("5d29bd7509f28633f38ccbfd", ObjectId("5d29bd7509f28633f38ccbfd", ObjectId("5d29bd7509f28633f38ccbfd"];
或post_id
属性进行索引。
2:查找
您应该使用category
方法,而不是使用简单的lookup
管道
例如:
不好。
pipeline
好。
$lookup:{
from: 'catagories',
localField: 'catagory.catagory_id', // BAD IDEA //
foreignField: '_id',
as: 'catagories_data'
},
更好
$lookup:{
from: 'catagories',
localField: '_id',
foreignField: 'post_id', // GOOD IDEA
as: 'catagories_data'
},
毕竟
$lookup:{
let : { post_id: "$_id" },
from: 'catagories',
pipeline:[
{
$match: {
$expr: {
$and: [
{ $eq: ["$post_id", "$$post_id"], },
]
}
},
},
{
$match: {
$or: [
// AVOID `new` keyword if you can do such;
// and create indexes for the same;
{ "catagory_name": { $regex: `^${search_data}` } },
{ "postname": { $regex: `^${search_data}` } },
{ "posturl": { $regex: `^${search_data}` } },
{ "postdata": { $regex: `^${search_data}` } },
{ "tags": { $regex: `^${search_data}` } }
]
}
}
],
as: 'catagories_data'
},
facet pipeline seems fine to me.
减速查询的其他方面取决于
完整查询如下所示
'$facet' : {
metadata: [ { $count: "total" }, { $addFields: { page: NumberInt(3) } } ],
data: [ { $skip: 20 }, { $limit: 10 } ] // add projection here wish you re-shape the docs
}
答案 1 :(得分:0)
如果在您的情况下,您的正则表达式只是在寻找一个(或几个)单词,那么最好使用$text而不是$ regex。 $ text可以使用文本索引,因此速度更快。对于 MySQL,$ text是LIKE,而$ regex是REGEXP 。由于在示例mysql查询中您使用的是LIKE,因此我非常有信心在mongo查询中也可以使用$ text而不是$ regex。
您需要在字段上(如果没有的话)有一个复合的“ text”索引-(帖子名称,标签,帖子数据和帖子网址)。
db.POST.createIndex(
{
postname: "text",
tags: "text",
posturl: "text",
postdata: "text"
}
)