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

How to search for text or expression in multiple fields

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;
            }
        });

我正在尝试实现所谓的 "all-in-one" 搜索,以便每当用户输入任何类型的电影相关信息时,我的应用程序都会尝试 return 所有相关信息。但是我注意到这个事务在后端可能很昂贵,有时主机真的很慢。

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

I read here that it is best not to close a mongodb connection in node.js >>Why is it recommended not to close a MongoDB connection anywhere in Node.js code?

  1. 使用嵌套查找命令来实现一体化搜索的正确方法是什么?

你现在的做法问题多多,没有必要这样做。您要做的就是在同一集合的多个字段中搜索可以收集的纯字符串。它可能是一个正则表达式构造,但我将两种可能性基于不区分大小写的纯文本搜索。

现在我不确定您是否运行宁一个查询依赖于另一个查询的结果,因为您不知道另一种方式,或者虽然它会更好。相信我,这不是比这里列出的任何方法更好的方法,也不是真正需要的,如下所示:

一次正则表达式查询

此处的第一个基本选项是继续您的 $regex search but just in a singular query with the $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 条件实际上像 "combining queries" 一样工作,因为就文档选择而言,每个参数本身都被视为查询。因为是一个查询,所以所有的结果自然就在一起了。

全文查询,多字段

如果您没有真正使用由正则表达式操作构建的 "regular expression",即 ^(\d+)\bword$,那么您最好使用 MongoDB 的 "text search" 功能。只要您不是在寻找通常会被排除在外的东西,这种方法就很好,但您的数据结构和主题实际上表明这是您可能在这里做的事情的最佳选择。

为了能够执行文本搜索,您首先需要创建一个"text index",具体在这里您希望索引跨越文档中的多个字段。进入 shell 可能是最简单的:

db.movies.createIndex({
   "original_title": "text",
   "release_date":   "text",
   "cast" :          "text",
   "writers" :       "text",
   "genres.name" :   "text",
   "directors" :     "text"
})

还有一个选项可以将 "weight" 分配给索引中的字段,您可以在文档中阅读。分配权重 "priority" 给在搜索中列出的匹配字段的术语。例如 "directors" 可能被分配的 "weight" 多于 "cast" 并且匹配 [=因此,92=] 会 "rank higher" 在结果中他是电影的导演(也是演员),而不仅仅是演员(就像大多数罗伯特·罗德里格斯的电影一样)。

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

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

几乎 太简单了 真的,但仅此而已。 $text 查询运算符知道使用所需的索引(每个集合只能有一个文本索引),然后它将查看所​​有定义的字段。

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

并行查询

我要在这里给出的最后一个替代方案是您仍然想要要求您 需要 到 运行 单独的查询。我仍然否认你确实需要仅在先前的查询没有 return 结果时进行查询,并且我还重申应考虑上述选项 "first",优先考虑文本搜索。

编写依赖或链式异步函数是一件痛苦,而且非常混乱。因此,我建议从另一个库依赖中获得一点帮助,并在此处使用 node-async 模块。

这提供了一种 aync.map.() 方法,非常适合通过 运行 并行处理 "combining" 结果:

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() 运算符获取每个字段并将其转置到查询中,而查询又是 return 的结果。在最后一节中的所有查询 运行 之后,这些结果就可以访问了,"combined" 就好像它们是单个结果集一样,就像这里的其他替代项一样。

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

我真的不认为这个选项是必要的,但是如果 Case 1 正则表达式语句仍然适用,这个 "may" 由于 运行 并行查询, 可能会提供一点性能优势,但是 以增加应用程序中的内存和资源消耗为代价。

总之,这里的汇总是"Don't do what you are doing",您不需要,而且有更好的方法来处理您想要完成的任务。而且所有这些都意味着更干净,更容易编码。