MongoDB:可以进行不区分大小写的查询吗?

MongoDB:可以进行不区分大小写的查询吗?,mongodb,case-insensitive,Mongodb,Case Insensitive,例如: > db.stuff.save({"foo":"bar"}); > db.stuff.find({"foo":"bar"}).count(); 1 > db.stuff.find({"foo":"BAR"}).count(); 0 你可以用一个小盒子 在您的示例中,这将是: db.stuff.find({foo://^bar$/i}); 不过,我必须说,也许你可以在进入的过程中降低(或提高)价值,而不是每次发现它都要付出额外的成本。显然,这不适用于人名等,但可能使

例如:

> db.stuff.save({"foo":"bar"});

> db.stuff.find({"foo":"bar"}).count();
1
> db.stuff.find({"foo":"BAR"}).count();
0
你可以用一个小盒子

在您的示例中,这将是:

db.stuff.find({foo://^bar$/i});

不过,我必须说,也许你可以在进入的过程中降低(或提高)价值,而不是每次发现它都要付出额外的成本。显然,这不适用于人名等,但可能使用标签之类的用例。

更新:

原来的答案现在已经过时了

原始答案:

需要注意的是,使用regex的不区分大小写/i进行搜索意味着mongodb无法按索引进行搜索,因此针对大型数据集的查询可能需要很长时间

即使是小数据集,也不是很有效。您需要比查询所需的cpu占用量大得多,如果您试图实现规模,这可能会成为一个问题

另一种选择是,您可以存储一个大写副本,并根据该副本进行搜索。例如,我有一个用户表,它的用户名是大小写混合的,但id是用户名的大写副本。这确保了不可能进行区分大小写的复制(不允许同时使用“Foo”和“Foo”),并且我可以通过id=username.toUpperCase()进行搜索,以获得对username的不区分大小写的搜索


如果您的字段很大,例如消息正文,那么复制数据可能不是一个好的选择。我相信在这种情况下,使用Apache Lucene这样的外部索引器是最好的选择。

最好的方法是使用您选择的语言,在为对象创建模型包装器时,让save()方法迭代一组您将搜索的字段,这些字段也会被索引;这些字段集应具有小写对应项,然后用于搜索

每次再次保存对象时,都会检查小写属性,并使用对主属性的任何更改进行更新。这将使您能够高效地搜索,但隐藏每次更新lc字段所需的额外工作

小写字段可以是key:value对象存储,也可以只是带有前缀lc_的字段名。我使用第二种方法来简化查询(深度对象查询有时会令人困惑)


注意:您希望索引lc_uu字段,而不是它们所基于的主字段

请记住前面的示例:

db.stuff.find( { foo: /bar/i } );
将导致包含条的每个条目与查询(bar1、barxyz、openbar)匹配,在身份验证函数上搜索用户名可能非常危险

您可能需要使用适当的regexp语法使其仅与搜索词匹配,如下所示:

db.stuff.find( { foo: /^bar$/i } );

有关正则表达式的语法帮助,请参阅。Mongo(当前版本2.0.0)不允许对索引字段进行不区分大小写的搜索。请参阅。对于非索引字段,其他答案中列出的正则表达式应该可以使用。

如果需要从变量创建正则表达式,这是一种更好的方法:

然后,您可以执行以下操作:

var string = "SomeStringToFind";
var regex = new RegExp(["^", string, "$"].join(""), "i");
// Creates a regex of: /^SomeStringToFind$/i
db.stuff.find( { foo: regex } );

这样做的好处是程序化程度更高,或者如果大量重复使用,可以通过提前编译来提高性能。

使用Mongoose这对我很有用:

var find = function(username, next){
    User.find({'username': {$regex: new RegExp('^' + username, 'i')}}, function(err, res){
        if(err) throw err;
        next(null, res);
    });
}
  const flavorExists = await Flavors.findOne({
    'flavor.name': { $regex: flavorName, $options: 'i' },
  });

我已经为不区分大小写的正则表达式创建了一个简单的Func,我在过滤器中使用它

private Func<string, BsonRegularExpression> CaseInsensitiveCompare = (field) => 
            BsonRegularExpression.Create(new Regex(field, RegexOptions.IgnoreCase));

假设您想要在“表”中搜索“列”,并且想要不区分大小写的搜索。最佳和有效的方法是:

//create empty JSON Object
mycolumn = {};

//check if column has valid value
if(column) {
    mycolumn.column = {$regex: new RegExp(column), $options: "i"};
}
Table.find(mycolumn);

它只是将您的搜索值添加为RegEx,并使用设置为“i”选项的不敏感条件进行搜索。

在使用基于RegEx的查询时,需要记住一件非常重要的事情-当您为登录系统执行此操作时,您正在搜索,并且不要忘记“^”和“$”运算符,如果您已经在使用它:

db.stuff.find({$regex: new RegExp(_.escapeRegExp(bar), $options: 'i'})
为什么??想象一个用户输入
*
作为他的用户名。这将匹配所有用户名,只需猜测任何用户的密码即可登录;博士

在mongo中执行此操作的正确方法 不要使用RegExp

步骤1: 步骤2: 需要在要搜索的文本字段上创建索引,如果不建立索引,查询速度将非常慢

db.articles.createIndex( { subject: "text" } )
步骤3:
从MongoDB 3.4开始,执行快速不区分大小写搜索的推荐方法是使用

我亲自给其中一位创始人发了电子邮件,希望他能让这一切顺利实现!这是一个很好的例子,很多人都要求这项功能。下面是它的工作原理:

不区分大小写的索引是通过指定强度为1或2的。您可以创建不区分大小写的索引,如下所示:

db.cities.createIndex(
{城市:1},
{ 
整理:{
地区:'en',
人数:2人
}
}
);
创建集合时,还可以为每个集合指定默认排序规则:

db.createCollection('cities', { collation: { locale: 'en', strength: 2 } } );
在这两种情况下,为了使用不区分大小写的索引,您需要在
find
操作中指定创建索引或集合时使用的相同排序规则:

db.cities.find(
{纽约市}
).整理(
{地区:'en',强度:2}
);
这将返回“纽约”、“纽约”、“纽约”等

其他注释
  • 在这种情况下,建议使用全文搜索的答案是错误的(并且有潜在危险)。问题是关于进行不区分大小写的查询,例如,
    用户名:“bill”
    匹配
    bill
    bill
    ,而不是全文搜索查询,该查询也会匹配
    bill
    的单词,例如
    Bills
    billed

  • 建议使用正则表达式的答案很慢,因为即使使用索引,也会:

    “不区分大小写的正则表达式查询通常无法有效地使用索引。$regex实现不区分排序规则,无法使用不区分大小写的索引。”

    $regex
    答案也有风险

  • db.articles.createIndex( { subject: "text" } )
    db.articles.find( { $text: { $search: "coffee",$caseSensitive :true } } )  //FOR SENSITIVITY
    db.articles.find( { $text: { $search: "coffee",$caseSensitive :false } } ) //FOR INSENSITIVITY
    
    
     
    
    db.createCollection('cities', { collation: { locale: 'en', strength: 2 } } );
    
    {'_id': /.*CM.*/}               ||find _id where _id contains   ->CM
    {'_id': /^CM/}                  ||find _id where _id starts     ->CM
    {'_id': /CM$/}                  ||find _id where _id ends       ->CM
    
    {'_id': /.*UcM075237.*/i}       ||find _id where _id contains   ->UcM075237, ignore upper/lower case
    {'_id': /^UcM075237/i}          ||find _id where _id starts     ->UcM075237, ignore upper/lower case
    {'_id': /UcM075237$/i}          ||find _id where _id ends       ->UcM075237, ignore upper/lower case
    
    string s = "searchTerm";
        var filter = Builders<Model>.Filter.Where(p => p.Title.ToLower().Contains(s.ToLower()));
                    var listSorted = collection.Find(filter).ToList();
                    var list = collection.Find(filter).ToList();
    
    var filter = Builders<Model>.Filter.Eq(p => p.Title.ToLower(), s.ToLower());
    
    /* 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
    
      const flavorExists = await Flavors.findOne({
        'flavor.name': { $regex: flavorName, $options: 'i' },
      });
    
    const escapeStringRegexp = require('escape-string-regexp')
    const name = 'foo'
    db.stuff.find({name: new RegExp('^' + escapeStringRegexp(name) + '$', 'i')})   
    
    var username = new RegExp("^" + "John" + "$", "i");;
    
    db.company_profile.find({ "companyName" : { "$regex" : "Nilesh" , "$options" : "i"}});
    
    collation := &mgo.Collation{
        Locale:   "en",
        Strength: 2, 
    }
    
    
    err := collection.Find(query).Collation(collation)
    
    db.stuff.find( { foo: /^\Qbar\E$/i } );