如何使用mongoose find获取包含字符串部分的所有值?

82

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

这是我的模式(Schema):

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

正如您所见,我在对象中嵌入了2个数组,假设作者的内容可能是这样的:authors:["Alex Ferguson", "Didier Drogba", "Cristiano Ronaldo", "Alex"]
我想要实现的是获取数组中所有名字为Alex的项。

到目前为止,如果值完全匹配,我已经能够获取值。但是,如果我尝试获取包含Alex的项,那么答案始终为[]。

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

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

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

            res.json(books);
        });

我尝试了一些方法,但都没有运气。{authors:{$elemMatch:req.query.q}} 和 {authors:{$in:[req.query.q]}}。

这个方法给我一个错误,并且在另一篇文章中说它非常低效。{$where:this.authors.indexOf(req.query.q) != -1}

我还尝试过 {authors:{$regex:"./value/i"}}。

Map-reduce可以正常工作,我需要使用另一种方法使其工作,以查看哪种方法更好?

非常感谢任何帮助。我确定这很容易,但我是NodeJS和MongoDB的新手,一直没有自己解决问题。

3个回答

199
您在标签中已经接近回答了这个问题。MongoDB 有一个 $regex 运算符,允许将正则表达式提交为查询。因此,如果您要查询包含“Alex”字符串的内容,则可以进行如下操作:
Books.find(
    { "authors": { "$regex": "Alex", "$options": "i" } },
    function(err,docs) { 
    } 
);

你也可以这样做:

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

    }
);

两者都是有效的,与您在文档中所示的正确支持语法尝试有所不同。但是,如果您实际上是在问“如何仅获取字符串中匹配'Alex'的'array'结果?”那么这有点不同。更复杂的匹配超过一个数组元素是聚合框架(或可能是mapReduce,但速度要慢得多)的领域,您需要“过滤”数组内容。您从相同的地方开始。关键在于$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) {

    }
)

2
选项“I”代表什么? - Sai Krishnadas
$options: 'i' 表示匹配时不区分大小写。默认情况下,它会搜索区分大小写的匹配。 - D. Rattansingh

26

查找标题包含cool的帖子,进行不区分大小写匹配: (非常酷也包含cool)

const s = 'cool'
const regex = new RegExp(s, 'i') // i for case insensitive
Posts.find({title: {$regex: regex}})

4

使用mongoose和$regex进行实时搜索

以下是获取以搜索文本开头的书籍的查询。

var result = await Books.find({ 'authors': { $regex: '^' + search_text, $options: 'i' } }).exec();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接