db.movies.find({"original_title" : {$regex: input_data, $options:'i'}}, function (err, datares){
if (err || datares == false) {
db.movies.find({"release_date" : {$regex: input_data + ".*", $options:'i'}}, function (err, datares){
if(err || datares == false){
db.movies.find({"cast" : {$regex: input_data, $options:'i'}}, function (err, datares){
if(err || datares == false){
db.movies.find({"writers" : {$regex: input_data, $options:'i'}}, function (err, datares){
if(err || datares == false){
db.movies.find({"genres.name" : {$regex: input_data, $options:'i'}}, function (err, datares){
if(err || datares == false){
db.movies.find({"directors" : {$regex: input_data, $options:'i'}}, function (err, datares){
if(err || datares == false){
res.status(451);
res.json({
"status" : 451,
"error code": "dataNotFound",
"description" : "Invalid Data Entry."
});
return;
} else{
res.json(datares);
return;
}
});
} else {
res.json(datares);
return;
}
});
} else {
res.json(datares);
return;
}
});
} else {
res.json(datares);
return;
}
});
} else {
res.json(datares);
return;
}
});
} else {
res.json(datares);
return;
}
});
我正在努力实现一个所谓的"一体化"搜索,以便每当用户键入任何类型的电影相关信息时,我的应用程序会尝试返回所有相关信息。但是我注意到这个事务在后端可能很昂贵,有时候主机很慢。
我在这里读到最好不要在node.js中关闭mongodb连接>> Why is it recommended not to close a MongoDB connection anywhere in Node.js code?
答案 0 :(得分:3)
您当前的方法充满了问题,没有必要这样做。您要做的就是搜索可以收集的内容是同一集合中多个字段中的普通字符串。它可能是一个正则表达式构造,但我基于不区分大小写的纯文本搜索有两种可能性。
现在我不确定你是否根据另一个人的结果运行一个查询,因为你不知道另一种方式或者它会更好。相信我,这不是一个比这里列出的更好的方法,也不是真正需要的,如下所示:
此处的第一个基本选项是继续进行$regex
搜索,但只能使用$or
运算符进行单一查询:
db.movies.find(
{
"$or": [
{ "original_title" : { "$regex": input_data, "$options":"i"} },
{ "release_date" : { "$regex": input_data, "$options":"i"} },
{ "cast" : { "$regex": input_data, "$options":"i"} },
{ "writers" : { "$regex": input_data, "$options":"i"} },
{ "genres.name" : { "$regex": input_data, "$options":"i"} },
{ "directors" : { "$regex": input_data, "$options":"i"} }
]
},
function(err,result) {
if(err) {
// respond error
} else {
// respond with data or empty
}
}
);
这里的$or
条件实际上就像"组合查询"因为就文档选择而言,每个参数本身都被视为一个查询。因为它是一个查询,而不是所有结果自然在一起。
如果你没有真正使用"正则表达式"从正则表达式操作构建,即^(\d+)\bword$
,那么你可能最好使用"文本搜索" MongoDB的功能。这种方法很好,只要你不寻找通常被排除的东西,但你的数据结构和主题实际上表明这是你可能在这里做的最佳选择。
为了能够执行文本搜索,您首先需要创建一个"text index",特别是在这里您希望索引跨越文档中的多个字段。为此放入shell可能是最简单的:
db.movies.createIndex({
"original_title": "text",
"release_date": "text",
"cast" : "text",
"writers" : "text",
"genres.name" : "text",
"directors" : "text"
})
还可以选择分配"重量"您可以在文档中阅读索引中的字段。分配权重给予优先级"搜索匹配的字段中列出的条款。例如" director"可能会分配更多" weight"比#"演员"和#34; Quentin Tarantino"因此会排名更高"在结果中,他是电影的导演(也是演员)而不仅仅是演员(就像大多数罗伯特罗德里格斯的电影一样)。
但有了这个,执行查询本身非常简单:
db.movies.find(
{ "$text": { "$search": input_data } },
function(err,result) {
if(err) {
// respond error
} else {
// respond with data or empty
}
}
);
几乎太简单了,但这就是它的全部内容。 $text
查询运算符知道使用所需的索引(每个集合只能有一个文本索引),然后它将查看所有已定义的字段。
这就是为什么我认为这是您用例的最合适。
我在这里给出的最后一个替代方案是,您仍然希望要求您需要来运行单独的查询。我仍然否认你只需要查询前一个查询是否没有返回结果,我还重申断言应该考虑上面的选项"首先",优先考虑文本搜索。
编写依赖或链式异步函数是痛苦,而且非常混乱。因此,我建议从其他库依赖项中获取一些帮助,并在此处使用node-async模块。
这提供了aync.map.()
方法,非常适合"组合"通过并行运行结果:
var fields = [
"original_title",
"release_date",
"cast",
"writers",
"genres.name",
"directors"
];
async.map(
fields,
function(field,callback) {
var search = {},
cond = { "$regex": input_data, "$options": "i" };
search[field] = cond; // assigns the field to search
db.movies.find(search,callback);
},
function(err,result) {
if(err) {
// respond error
} else {
// respond with data or empty
}
}
);
再一次,就是这样。 .map()
运算符获取每个字段并将其转置到查询中,然后查询返回其结果。然后,在最后一节中运行所有查询后,可以访问这些结果,"合并"好像它们是单个结果集一样,就像其他替代方案一样。
还有一个.mapSeries()
变体可以串行运行每个查询,如果您担心使用数据库连接和并发任务,则会.mapLimit()
,但对于这个小尺寸,这应该不是问题
我真的不认为这个选项是必要的,但是如果 Case 1 正则表达式语句仍然适用,那么"可能" 由于并行运行查询,但可能会提供一点性能优势,但会增加应用程序内存和资源消耗。
无论如何,这里的回合是"不要做你正在做的事情" ,你不需要并且有更好的方法来处理你想要实现的任务。而且所有这些都更清晰,更容易编码。