node.js 如何使用猫鼬查找获取包含部分字符串的所有值?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26814456/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 18:05:41  来源:igfitidea点击:

How to get all the values that contains part of a string using mongoose find?

regexnode.jsmongodbmongodb-queryaggregation-framework

提问by Dyan

I have the following problem retrieving data from MongoDB using mongoose.

我在使用 mongoose 从 MongoDB 检索数据时遇到以下问题。

Here is my Schema:

这是我的架构:

const BookSchema = new Schema(
    {
        _id:Number,
        title:String,
        authors:[String],
        subjects:[String]   
    }
);

as you can see i have 2 arrays embedded in the object, let's say the content of the authors can be something like this: authors:["Alex Ferguson", "Didier Drogba", "Cristiano Ronaldo", "Alex"]
what I'm trying to achieve is get all the Alex in the array.

如您所见,我在对象中嵌入了 2 个数组,假设作者的内容可以是这样的:authors:["Alex Ferguson", "Didier Drogba", "Cristiano Ronaldo", "Alex"]
我是什么我试图实现的是获取数组中的所有亚历克斯。

So far, I've been able to get the values if they match the value completely. However if I try to get the ones containing Alex the answer is always [].

到目前为止,如果它们完全匹配值,我已经能够获得这些值。但是,如果我尝试获取包含 Alex 的内容,答案始终是 []。

What I want to know is how I can do this using find() without performing a map-reduce to create a view or a collection and then applying find() over that.

我想知道的是如何使用 find() 来做到这一点,而无需执行 map-reduce 来创建视图或集合,然后对其应用 find() 。

The code here works for exact matches

这里的代码适用于完全匹配

Book.find( {authors:req.query.q} , function(errs, books){
            if(errs){
                res.send(errs); 
            }

            res.json(books);
        });

I tried some things but no luck {authors:{$elemMatch:req.query.q}} {authors:{$in:[req.query.q]}}

我尝试了一些东西但没有运气 {authors:{$elemMatch:req.query.q}} {authors:{$in:[req.query.q]}}

This one gives me an error and on top of that says is very inefficient in another post I found here. {$where:this.authors.indexOf(req.query.q) != -1}

这个给了我一个错误,最重要的是在我在这里找到的另一篇文章中说效率很低。{$where:this.authors.indexOf(req.query.q) != -1}

and I also tried {authors:{$regex:"./value/i"}}

我也试过 {authors:{$regex:"./ value/i"}}

The map-reduce works fine, I need to make it work using the other approach to see which one is better?

map-reduce 工作正常,我需要使用另一种方法让它工作,看看哪个更好?

Any help is greatly appreciated. I'm sure this is easy, but I'm new with NodeJS and Mongo and I haven't been able to figure it out on my own.

任何帮助是极大的赞赏。我确信这很容易,但我是 NodeJS 和 Mongo 的新手,我无法自己弄清楚。

回答by Neil Lunn

You almost answered this yourself in your tags. MongoDB has a $regexoperator which allows a regular expression to be submitted as a query. So you query for strings containing "Alex" you do this:

您几乎自己在标签中回答了这个问题。MongoDB 有一个$regex运算符,它允许将正则表达式作为查询提交。因此,您查询包含“Alex”的字符串,您可以这样做:

Books.find(
    { "authors": { "$regex": "Alex", "$options": "i" } },
    function(err,docs) { 
    } 
);

You can also do this:

你也可以这样做:

Books.find(
    { "authors": /Alex/i }, 
    function(err,docs) { 

    }
);

Both are valid and different to how you tried in the correct supported syntax as shown in the documentation.

两者都是有效的,并且与您在文档中显示的正确支持的语法中尝试的方式不同。

But of course if you are actually asking "how to get the 'array' results only for those that match 'Alex' somewhere in the string?" then this is a bit different.

但是,当然,如果您实际上是在问“如何仅针对与字符串中某个位置的 'Alex' 匹配的那些来获取 'array' 结果?” 那么这有点不同。

Complex matching for more than onearray element is the domain of the aggregation framework( or possibly mapReduce, but that is much slower ), where you need to "filter" the array content.

超过复杂的匹配一个数组元素是域聚合框架(或可能的MapReduce,但这是很慢),在需要“过滤器”的数组的内容。

You start of much the same. The key here is to $unwindto "de-normalize" the array content in order to be alble to "filter" properly as individual documents. Then re-construct the array with the "matching" documents.

你的开始大同小异。这里的关键是对$unwind数组内容进行“反规范化”,以便能够像单个文档一样正确地“过滤”。然后使用“匹配”文档重新构建数组。

Books.aggregate(
    [
        // Match first to reduce documents to those where the array contains the match
        { "$match": {
            "authors": { "$regex": "Alex", "$options": i }
        }},

        // Unwind to "de-normalize" the document per array element
        { "$unwind": "$authors" },

        // Now filter those document for the elements that match
        { "$match": {
            "authors": { "$regex": "Alex", "$options": i }
        }},

        // Group back as an array with only the matching elements
        { "$group": {
            "_id": "$_id",
            "title": { "$first": "$title" },
            "authors": { "$push": "$authors" },
            "subjects": { "$first": "$subjects" }
        }}
    ],
    function(err,results) {

    }
)