如何在Mongodb上进行不区分大小写的查询?


93
var thename = 'Andrew';
db.collection.find({'name':thename});

如何查询不区分大小写?我想找到结果,即使“安德鲁”;



给所有尝试使用涉及正则表达式的答案的人的注释:需要对正则表达式进行清理。
肖恩

Answers:


126

克里斯·富尔斯托(Chris Fulstow)的解决方案可以工作(+1),但是,它可能并不高效,特别是如果您的馆藏很大的话。非根正则表达式(不以开头^的正则表达式将正则表达式锚定到字符串的开头),并且使用i标志区分大小写的表达式将不使用索引,即使它们存在也是如此。

您可能考虑的另一种选择是对数据进行非规范化以存储name字段的小写版本,例如name_lower。然后,您可以有效地查询(特别是如果已编制索引)不区分大小写的精确匹配,例如:

db.collection.find({"name_lower": thename.toLowerCase()})

或使用前缀匹配(有根正则表达式)为:

db.collection.find( {"name_lower":
    { $regex: new RegExp("^" + thename.toLowerCase(), "i") } }
);

这两个查询都将使用的索引name_lower


1
很好的答案,我的正则表达式方法一旦必须扫描几百万个文档,实际上就会放慢速度。
克里斯·富斯托

34
这实际上并不完全正确,因为在查找“ Andrew”时可能会找到“ Andrew something”。因此,将正则表达式调整为:new RegExp('^'+ username + '$', "i")完全匹配。
Tarion 2014年

9
根据MongoDB网站,任何不区分大小写的正则表达式都不能有效使用索引:“只有当正则表达式具有字符串开头(即^)的锚并且是区分大小写的匹配项时,$ regex才可以有效地使用索引”
Ryan Schumacher

2
使用Mongoose可以为我工作:User.find({'username':{$ regex:new RegExp('^'+ username.toLowerCase(),'i')}}},function(err,res){if(err )throw err; next(null,res);});
ChrisRich 2014年

5
使用正则表达式时,请不要忘记转义该名称。我们不希望注射剂取代mongodb的美丽。试想一下,您将此代码用于登录页面,用户名是".*"
Tobias 2014年

90

您需要为此使用不区分大小写的正则表达式,例如

db.collection.find( { "name" : { $regex : /Andrew/i } } );

要使用thename变量中的regex模式,请构造一个新的RegExp对象:

var thename = "Andrew";
db.collection.find( { "name" : { $regex : new RegExp(thename, "i") } } );

更新:对于完全匹配,您应该使用regex "name": /^Andrew$/i。感谢Yannick L.


7
您知道如何使用Node.js猫鼬吗?
user847495 2011年

1
我想知道这与大型收藏集的搭配效果如何。您会失去排序功能的好处
Wilfred Springer

5
这是错误的,它将匹配包含的“ andrew”的所有文档name,而不仅仅是匹配。
乔纳森·克雷敏

14
@JonathanCremin帮助人们,您应该发布正确的答案:{ "name": /^Andrew$/i }
Yannick Loriot 2014年

@YannickL。1+用于做常识性事情。我只是路过而不是我要找的东西。
Lpc_dark 2015年

38

我已经解决了这个问题。

 var thename = 'Andrew';
 db.collection.find({'name': {'$regex': thename,$options:'i'}});

如果要查询“不区分大小写的精确匹配”,则可以这样进行。

var thename =  '^Andrew$';
db.collection.find({'name': {'$regex': thename,$options:'i'}});

7

MongoDB 3.4现在包含创建真实的不区分大小写索引的功能,这将大大提高大型数据集上不区分大小写的查找速度。通过指定强度为2的排序规则来完成。

可能最简单的方法是在数据库上设置排序规则。然后所有查询都继承该排序规则并将使用它:

db.createCollection("cities", { collation: { locale: 'en_US', strength: 2 } } )
db.names.createIndex( { city: 1 } ) // inherits the default collation

您也可以这样做:

db.myCollection.createIndex({city: 1}, {collation: {locale: "en", strength: 2}});

并像这样使用它:

db.myCollection.find({city: "new york"}).collation({locale: "en", strength: 2});

这将返回名为“纽约”,“纽约”,“纽约”等的城市。

有关更多信息:https : //jira.mongodb.org/browse/SERVER-90


强度:1足以区分大小写,不区分变音符号。docs.mongodb.com/manual/reference/collat​​ion
Gaurav Ragtah

7
  1. 与猫鼬(和节点),这工作:

    • User.find({ email: /^name@company.com$/i })

    • User.find({ email: new RegExp(`^ $ {emailVariable} $`,'i')})

  2. 在MongoDB中,这有效:

    • db.users.find({ email: { $regex: /^name@company.com$/i }})

这两行都不区分大小写。数据库中的电子邮件可能是,NaMe@CompanY.Com并且两行仍将在数据库中找到对象。

同样,我们可以使用/^NaMe@CompanY.Com$/i并且它仍会name@company.com在数据库中找到电子邮件:。



4

几个小时前我刚刚解决了这个问题。

var thename = 'Andrew'
db.collection.find({ $text: { $search: thename } });
  • 以这种方式进行查询时,区分大小写和变音符号的默认设置为false。

您甚至可以通过以下方式从Andrew用户对象中选择所需的字段来扩展此功能:

db.collection.find({ $text: { $search: thename } }).select('age height weight');

参考:https : //docs.mongodb.org/manual/reference/operator/query/text/#text


1
$ text对使用文本索引索引的字段的内容执行文本搜索。
SSH

4

...在NodeJS上使用猫鼬查询:

const countryName = req.params.country;

{ 'country': new RegExp(`^${countryName}$`, 'i') };

要么

const countryName = req.params.country;

{ 'country': { $regex: new RegExp(`^${countryName}$`), $options: 'i' } };

// ^australia$

要么

const countryName = req.params.country;

{ 'country': { $regex: new RegExp(`^${countryName}$`, 'i') } };

// ^turkey$

Java语言中的完整代码示例,MongoDB上带有Mongoose ORM的NodeJS

// get all customers that given country name
app.get('/customers/country/:countryName', (req, res) => {
    //res.send(`Got a GET request at /customer/country/${req.params.countryName}`);

    const countryName = req.params.countryName;

    // using Regular Expression (case intensitive and equal): ^australia$

    // const query = { 'country': new RegExp(`^${countryName}$`, 'i') };
    // const query = { 'country': { $regex: new RegExp(`^${countryName}$`, 'i') } };
    const query = { 'country': { $regex: new RegExp(`^${countryName}$`), $options: 'i' } };

    Customer.find(query).sort({ name: 'asc' })
        .then(customers => {
            res.json(customers);
        })
        .catch(error => {
            // error..
            res.send(error.message);
        });
});

1

以下查询将不敏感地找到带有所需字符串的文档,并且还全局出现

db.collection.find({name:{
                             $regex: new RegExp(thename, "ig")
                         }
                    },function(err, doc) {
                                         //Your code here...
                  });

1

查找不区分大小写的文字字符串:

使用正则表达式(推荐)

db.collection.find({
    name: {
        $regex: new RegExp('^' + name.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '$', 'i')
    }
});

使用小写索引(更快)

db.collection.find({
    name_lower: name.toLowerCase()
});

正则表达式比文字字符串匹配慢。但是,附加的小写字段会增加代码的复杂性。如有疑问,请使用正则表达式。我建议仅在可以替换您的字段的情况下才使用显式小写的字段,也就是说,您首先不关心大小写。

请注意,您需要在正则表达式前转义该名称。如果要使用用户输入的通配符,则最好.replace(/%/g, '.*')在转义后附加,以便可以匹配“ a%”以查找所有以“ a”开头的名称。


1

您可以使用不区分大小写的索引

下面的示例创建一个没有默认归类的集合,然后使用不区分大小写的归类在名称字段上添加索引。Unicode的国际组件

/*
* strength: CollationStrength.Secondary
* Secondary level of comparison. Collation performs comparisons up to secondary * differences, such as diacritics. That is, collation performs comparisons of 
* base characters (primary differences) and diacritics (secondary differences). * Differences between base characters takes precedence over secondary 
* differences.
*/
db.users.createIndex( { name: 1 }, collation: { locale: 'tr', strength: 2 } } )

要使用索引,查询必须指定相同的排序规则。

db.users.insert( [ { name: "Oğuz" },
                            { name: "oğuz" },
                            { name: "OĞUZ" } ] )

// does not use index, finds one result
db.users.find( { name: "oğuz" } )

// uses the index, finds three results
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 2 } )

// does not use the index, finds three results (different strength)
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 1 } )

或者您可以使用默认排序规则创建一个集合:

db.createCollection("users", { collation: { locale: 'tr', strength: 2 } } )
db.users.createIndex( { name : 1 } ) // inherits the default collation

-3

一种简单的方法是使用$ toLower,如下所示。

db.users.aggregate([
    {
        $project: {
            name: { $toLower: "$name" }
        }
    },
    {
        $match: {
            name: the_name_to_search
        }
    }
])
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.