如何在多个字段中搜索文本或表达式

sum*_*ght 1 mongodb mongodb-query mongojs

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;
            }
        });
Run Code Online (Sandbox Code Playgroud)

我正在尝试实现所谓的“多合一”搜索,以便每当用户键入任何类型的电影相关信息时,我的应用程序都将尝试返回所有相关信息。但是我注意到,此事务在后端可能很昂贵,有时主机确实很慢。

  1. 如何顺利关闭数据库连接,该在哪里使用?

我在这里读到最好不要在node.js中关闭mongodb连接>> 为什么建议不要在Node.js代码中的任何位置都关闭MongoDB连接?

  1. 通过使用嵌套的find命令来实现一种多合一搜索的正确方法吗?

Bla*_*ven 5

您当前的方法充满了问题,不需要这样做。您要做的就是在同一集合的多个字段中搜索罐头收集的内容是纯字符串。它可能是一个正则表达式构造,但是我基于两种不区分大小写的纯文本搜索。

现在,我不确定您是否要根据另一个查询的结果来运行一个查询,因为您不知道另一种方式,尽管这样做会更好。相信我,这不是比这里列出的任何方法更好的方法,也并非如以下所示真正需要它:

正则表达式一次查询

这里的第一个基本选项是继续$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
        }
    }
);
Run Code Online (Sandbox Code Playgroud)

$or就文档选择而言,这里的条件实际上像“合并查询”一样有效,因为每个参数本身都被视为查询。由于这是一个查询,因此所有结果自然都在一起。

全文查询,多个字段

如果您不是真正使用从正则表达式操作(即)构建的“正则表达式” ^(\d+)\bword$,那么最好使用MongoDB的“文本搜索”功能。只要您不查找通常不会被排除的内容,这种方法就可以了,但是您的数据结构和主题实际上表明这是您可能在此处进行操作的最佳选择。

为了能够执行文本搜索,首先需要创建一个“文本索引”,特别是在这里,您希望索引跨越文档中的多个字段。为此,放入外壳可能是最简单的:

db.movies.createIndex({
   "original_title": "text",
   "release_date":   "text",
   "cast" :          "text",
   "writers" :       "text",
   "genres.name" :   "text",
   "directors" :     "text"
})
Run Code Online (Sandbox Code Playgroud)

您也可以选择在文档中为索引中的字段分配“权重”。分配权重会将“优先级”赋予在搜索条件中匹配的字段中列出的术语。例如,“导演”的权重可能比“演员”的权重更高,因此“昆汀·塔伦蒂诺”的匹配项将“排名更高”结果是他是电影的导演(也是演员),而不仅仅是演员(就像罗伯特·罗德里格斯的大多数电影一样)。

但是有了这个,执行查询本身非常简单:

db.movies.find(
    { "$text": { "$search": input_data }  },
    function(err,result) {
        if(err) {
           // respond error
        } else {
           // respond with data or empty
        }
    }
);
Run Code Online (Sandbox Code Playgroud)

真的几乎太简单了,但这就是全部。该$text查询运营商知道使用所需指数(只能有每收集一个文本索引),它只会再通过所有的定义的字段的样子。

这就是为什么我认为这最适合您的用例。

并行查询

我在这里要给出的最后一个替代方案是,您仍然希望要求您需要运行单独的查询。我仍然否认您只需要查询如果先前的查询不返回结果,并且我还断言上述选项应被认为是“ first”(优先于文本搜索)。

编写依赖或链接的异步函数是一件很痛苦的事情,而且非常混乱。因此,我建议从另一个库依赖项中获取一些帮助,并在此处使用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
        }
    }
);
Run Code Online (Sandbox Code Playgroud)

再说一遍。该.map()操作需要每个字段并转置到这一点而这又回到它的结果的查询。在所有查询在最后一节中运行之后,可以将这些结果“合并”起来,就好像它们是单个结果集一样,就像其他替代方法在这里一样。

还有一个.mapSeries()变体可以按顺序运行每个查询,或者.mapLimit()如果您担心使用数据库连接和并发任务,但是对于这么小的体积,这应该不是问题。

我真的不认为此选项是必要的,但是,如果仍然使用Case 1正则表达式语句,则由于并行运行查询,此“可能”可能会带来一点性能上的好处,但是会增加内存和资源的消耗在您的应用程序中。

无论如何,这里的内容是“不要做您正在做的事情”,您不需要做的事,还有更好的方法来处理您要完成的任务。所有这些都意味着更清洁,更容易编写代码。