当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《MongoDB:是否可以进行不区分大小写的查询?》经验,为你挑选了13个好方法。

例:

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

> db.stuff.find({"foo":"bar"}).count();
1
> db.stuff.find({"foo":"BAR"}).count();
0

rfunduk.. 313

你可以使用正则表达式.

在你的例子中将是:

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

但是,我必须说,也许你可以在途中减少(或取消)价值,而不是每次发现它都会产生额外费用.显然,这不适用于人们的名字等,但也许像标签这样的用例.



1> rfunduk..:

你可以使用正则表达式.

在你的例子中将是:

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

但是,我必须说,也许你可以在途中减少(或取消)价值,而不是每次发现它都会产生额外费用.显然,这不适用于人们的名字等,但也许像标签这样的用例.


这非常有效.在PHP中使用:$ collection-> find(array('key'=> new MongoRegex('/'.$ val.'/ i')));
请注意,这将执行fullscan而不是使用索引.
别忘了^和$:MongoRegex('/ ^'.preg_quote($ val).'$/i')
如果他在开始时使用^锚点,它将不会执行fullscan,因此Julien的建议的重要性.
特别是如果你要插入一个可能有问号的字符串({foo:/#{x}/i}).

2> Dan..:

更新:

原来的答案现在已经过时了.Mongodb现在支持高级全文搜索,具有许多功能.

原始答案:

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

即使使用小型数据集,它也不是很有效.你获得的cpu命中率远高于你的查询保证,如果你试图达到规模,这可能会成为一个问题.

作为替代方案,您可以存储大写副本并对其进行搜索.例如,我有一个User表,其用户名是大小写混合的,但id是用户名的大写副本.这样可以确保区分大小写的复制是不可能的(不允许使用"Foo"和"foo"),并且我可以通过id = username.toUpperCase()进行搜索,以获得对用户名不区分大小写的搜索.

如果您的字段很大,例如邮件正文,则复制数据可能不是一个好选择.我相信在这种情况下使用像Apache Lucene这样无关的索引器是最好的选择.


@SergiySokolenko:文档现在说((本节的最后一段)(https://docs.mongodb.com/manual/reference/operator/query/regex/#index-use)):“通常不区分大小写的正则表达式查询无法有效地使用索引。$ regex实现不支持排序规则,也无法利用不区分大小写的索引。”

3> jflaflamme..:

请记住前面的示例:

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

将导致包含bar的每个条目与查询匹配(bar1,barxyz,openbar),对auth函数的用户名搜索可能非常危险...

您可能需要使用适当的regexp语法使其仅匹配搜索项:

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

有关正则表达式的语法帮助,请参见http://www.regular-expressions.info/



4> Fotios..:

如果您需要从变量创建正则表达式,这是一个更好的方法:https://stackoverflow.com/a/10728069/309514

然后你可以这样做:

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

这样做的好处是更具编程性,或者如果您重复使用它,可以通过提前编译来提高性能.



5> user3413723..:

从Mongodb 3.4开始,您应该使用不区分大小写的排序规则索引.这是对越来越大的数据集进行不区分大小写搜索的最快方法.我亲自通过电子邮件向其中一位创始人发送电子邮件,以便让它正常运行,并且他实现了这一目标!(这是JIRA的一个问题,就像5年一样,很多人都要求这个功能).以下是它的工作原理:

通过指定强度为1或2的排序规则来创建不区分大小写的索引.您可以创建不区分大小写的索引,如下所示:

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

或者,您可以在创建数据库时默认为整个集合执行此操作,如下所示:

db.createCollection('cities', { collation: { locale: 'en', strength: 2 } } );

并像这样使用它:

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

这将返回"纽约","纽约"等.

或者,您可以在制作集合时默认情况下使所有索引都使用排序规则:

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

这种方法的好处是大大提高了更大数据集的效率和速度.

欲了解更多信息:https://jira.mongodb.org/browse/SERVER-90,https://docs.mongodb.com/manual/reference/collat​​ion/



6> 小智..:
db.zipcodes.find({city : "NEW YORK"}); // Case-sensitive
db.zipcodes.find({city : /NEW york/i}); // Note the 'i' flag for case-insensitivity


@ParthTrivedi,评论只要代码本身.你想要3页的文章吗?

7> vijay..:

TL; DR

正确的方法在mongo中这样做

不要使用RegExp

自然而然地使用mongodb的内置索引,搜索

步骤1 :

db.articles.insert(
   [
     { _id: 1, subject: "coffee", author: "xyz", views: 50 },
     { _id: 2, subject: "Coffee Shopping", author: "efg", views: 5 },
     { _id: 3, subject: "Baking a cake", author: "abc", views: 90  },
     { _id: 4, subject: "baking", author: "xyz", views: 100 },
     { _id: 5, subject: "Café Con Leche", author: "abc", views: 200 },
     { _id: 6, subject: "???????", author: "jkl", views: 80 },
     { _id: 7, subject: "coffee and cream", author: "efg", views: 10 },
     { _id: 8, subject: "Cafe con Leche", author: "xyz", views: 10 }
   ]
)

第2步 :

需要在要搜索的任何TEXT字段上创建索引,而不进行索引查询将非常慢

db.articles.createIndex( { subject: "text" } )

第3步:

db.articles.find( { $text: { $search: "coffee",$caseSensitive :true } } )  //FOR SENSITIVITY
db.articles.find( { $text: { $search: "coffee",$caseSensitive :false } } ) //FOR INSENSITIVITY


除了正则表达式要慢得多。全文搜索也很慢,但并不慢。最快(但更肿)的方式是将始终设置为小写的单独字段。

8> Nilesh..:
db.company_profile.find({ "companyName" : { "$regex" : "Nilesh" , "$options" : "i"}});



9> Aidan Feldma..:

Mongo(当前版本2.0.0)不允许对索引字段进行不区分大小写的搜索 - 请参阅其文档.对于非索引字段,其他答案中列出的正则表达式应该没问题.


只是为了澄清这一点:在索引字段上不区分大小写的搜索是_allowed_,它们只是不会使用索引,并且会像没有索引字段一样慢.

10> RobKohr..:

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

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

小写字段可以是键:值对象存储或仅带有前缀lc_的字段名称.我使用第二个来简化查询(深层对象查询有时会令人困惑).

注意:您要索引lc_字段,而不是它们所基于的主要字段.



11> ChrisRich..:

使用Mongoose这对我有用:

var find = function(username, next){
    User.find({'username': {$regex: new RegExp('^' + username, 'i')}}, function(err, res){
        if(err) throw err;
        next(null, res);
    });
}


如果你指定`i`的不区分大小写的标志,那么`.toLowerCase()`不是多余的吗?
这很危险。您没有在转义用户名,因此可以插入任意正则表达式。

12> Ankur Soni..:

假设您要在"表"中搜索"列",并且您希望不区分大小写搜索.最好,最有效的方法如下;

//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"的insensitve条件作为选项进行搜索.

祝一切顺利.



13> 小智..:

使用基于Regex的查询时要记住的一件非常重要的事情 - 当您为登录系统执行此操作时,请转义要搜索的每个字符,并且不要忘记^和$运算符.如果你已经使用它,Lodash有一个很好的功能:

db.stuff.find({$regex: new RegExp(_.escapeRegExp(bar), $options: 'i'})

为什么?想象一下用户输入.*他的用户名.这将匹配所有用户名,只需猜测任何用户的密码即可启用登录.

推荐阅读
135369一生真爱_890
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有