如何在多个字段中搜索文本或表达式 [英] How to search for text or expression in multiple fields

查看:92
本文介绍了如何在多个字段中搜索文本或表达式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

I am trying to implement a so called "all-in-one" search so that whenever a user types in any kind of movie related information, my application tries to return all relevant information. However I have noticed that this transaction might be expensive on the backend and sometimes the host is really slow.

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

我在这里读到最好不要在node.js中关闭mongodb连接>>

  1. 通过嵌套的查找命令实现事物的多合一搜索的正确方法吗?

推荐答案

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

Your current approach is full of problems and is not necessary to do this way. All you are trying to do is search for what a can gather is a plain string within a number of fields in the same collection. It may possibly be a regular expression construct but I'm basing two possibilities on a plain text search that is case insensitive.

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

Now I am not sure if you came to running one query dependant on the results of another because you didn't know another way or though it would be better. Trust me on this, that is not a better approach than anything listed here nor is it really required as will be shown:

这里的第一个基本选项是继续您的 $regex 搜索,但仅使用 $or 运算符:

The first basic option here is to continue your $regex search but just in a singular query with the $or operator:

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条件有效地类似于合并查询",因为就文档选择而言,每个参数本身都被视为查询.由于这是一个查询,所以所有结果自然都在一起.

The $or condition here effectively works like "combining queries" as each argument is treated as a query in itself as far as document selection goes. Since it is one query than all the results are naturally together.

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

If you are not really using a "regular expression" built from regular expression operations i.e ^(\d+)\bword$, then you are probably better off using the "text search" capabilities of MongoDB. This approach is fine as long as you are not looking for things that would be generally excluded, but your data structure and subject actually suggests this is the best option for what you are likely doing here.

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

In order to be able to perform a text search, you first need to create a "text index", specifically here you want the index to span multiple fields in your document. Dropping into the shell for this is probably easiest:

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

还有一个选项可以为索引中的字段分配权重",您可以在文档中阅读.分配权重会将优先级"赋予在搜索条件中匹配的字段中列出的术语.例如,导演"的权重可能比演员"的权重更高,因此昆汀·塔伦蒂诺"的匹配项将排名更高"结果表明,他是电影的导演(也是演员),而不仅仅是罗伯特·罗德里格斯(Robert Rodriguez)电影中的演员.

There is also an option to assign a "weight" to fields within the index as you can read in the documentation. Assigning a weight give "priority" to the terms listed in the search for the field that match in. For example "directors" might be assigned more "weight" than "cast" and matches for "Quentin Tarantino" would therefore "rank higher" in the results where he was a director ( and also a cast member ) of the movie and not just a cast member ( as in most Robert Rodriguez films ).

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

But with this in place, performing the query itself is very simple:

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

实际上太简单,但这就是全部. $text 查询操作员知道使用所需的索引(每个集合只能有一个文本索引),然后它将浏览所有已定义的字段.

Almost too simple really, but that is all there is to it. The $text query operator knows to use the required index ( there can only be one text index per collection ) and it will just then look through all of the defined fields.

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

This is why I think this is the best fit for your use case here.

我在这里要提供的最后一个替代方法是,您仍然希望您需要来运行单独的查询.我仍然否认您只需要在前一个查询未返回结果的情况下进行查询,并且我还重申上述选项应优先考虑优先",优先考虑文本搜索.

The final alternate I'll give here is you still want to demand that you need to run separate queries. I still deny that you do need to only query if the previous query does not return results, and I also re-assert that the above options should be considered "first", with preference to text search.

编写依赖或链接的异步函数会很痛苦,而且很混乱.因此,我建议从另一个库依赖项中获取一些帮助,并在此处使用 node-async 模块.

Writing dependant or chained asynchronous functions is a pain, and very messy. Therefore I suggest leaning a little help from another library dependency and using the node-async module here.

这提供了 aync.map.() 方法,该方法非常适合通过组合"结果并行运行事物:

This provides an aync.map.() method, which is perfectly suited to "combining" results by running things in parallel:

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()运算符获取每个字段并将其转置到查询中,查询又返回其结果.在所有查询都在最后一节中运行之后,可以将这些结果合并"起来,就好像它们是单个结果集一样,就像其他替代方法在这里所做的一样.

And again, that is it. The .map() operator takes each field and transposes that into the query which in turn returns it's results. Those results are then accessible after all queries are run in the final section, "combined" as if they were a single result set, just as the other alternates do here.

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

There is also a .mapSeries() variant that runs each query in series, or .mapLimit() if you are otherwise worried about using database connections and concurrent tasks, but for this small size this should not be a problem.

我真的不认为此选项是必需的,但是,如果 Case 1 正则表达式语句仍然适用,则"may" 可能会带来一点性能上的好处由于并行运行查询,所以但是以增加应用程序中的内存和资源消耗为代价.

I really don't think that this option is necessary, however if the Case 1 regular expression statements still apply, this "may" possibly provide a little performance benefit due to running queries in parallel, but at the cost of increased memory and resource consumption in your application.

无论如何,这里的总结是不要做您正在做的事情" ,您不需要这样做,并且有更好的方法来处理您要完成的任务.所有这些都意味着更清洁,更容易编写代码.

Anyhow, the round up here is "Don't do what you are doing", you don't need to and there are better ways to handle the task you want to achieve. And all of them are mean cleaner and easier to code.

这篇关于如何在多个字段中搜索文本或表达式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆