Answers:
您可以使用正则表达式。
在您的示例中将是:
db.stuff.find( { foo: /^bar$/i } );
不过,我必须说,也许您可以在输入过程中小写(或大写)该值,而不是每次找到它都会产生额外的成本。显然,这不适用于人们的姓名等,但可能适用于诸如标签之类的用例。
更新:
原始答案现在已过时。Mongodb现在支持具有许多功能的高级全文搜索。
原始答案:
应该注意的是,使用正则表达式的不区分大小写的/ i进行搜索意味着mongodb无法按索引搜索,因此对大型数据集的查询可能需要很长时间。
即使数据集很小,它也不是很有效。您获得的CPU命中率比查询授权要大得多,如果您要实现规模化,这可能会成为一个问题。
或者,您可以存储大写副本并对其进行搜索。例如,我有一个User表,该表的用户名是大小写混合的,但是id是用户名的大写副本。这确保了区分大小写的复制是不可能的(不允许同时使用“ Foo”和“ foo”),并且我可以通过id = username.toUpperCase()进行搜索,以获取不区分大小写的用户名搜索。
如果您的字段很大(例如消息正文),则复制数据可能不是一个好的选择。我认为在这种情况下,使用像Apache Lucene这样的无关紧要的索引器是最好的选择。
如果需要从变量创建正则表达式,这是一种更好的方法: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 } );
这具有更多编程性的好处,或者,如果您经常重复使用它,则可以通过提前编译它来提高性能。
new RegExp("^" + req.params.term.toLowerCase(), "i")
也可以正常工作
请记住,前面的示例:
db.stuff.find( { foo: /bar/i } );
会导致每个包含bar的条目都与查询匹配(bar1,barxyz,openbar),这对于在auth函数上进行用户名搜索可能非常危险...
您可能需要使用适当的regexp语法,使其仅与搜索词匹配:
db.stuff.find( { foo: /^bar$/i } );
有关正则表达式的语法帮助,请参见http://www.regular-expressions.info/
从MongoDB 3.4开始,执行快速不区分大小写的搜索的推荐方法是使用不区分大小写的索引。
我亲自给其中一位创始人发了电子邮件,请他完成这项工作,而他做到了!自2009年以来,这一直是JIRA的问题,许多人都要求使用此功能。运作方式如下:
通过指定强度为1或2 的排序规则,可以创建不区分大小写的索引。您可以创建一个不区分大小写的索引,如下所示:
db.cities.createIndex(
{ city: 1 },
{
collation: {
locale: 'en',
strength: 2
}
}
);
您还可以在创建集合时为每个集合指定默认排序规则:
db.createCollection('cities', { collation: { locale: 'en', strength: 2 } } );
无论哪种情况,为了使用不区分大小写的索引,您都需要find
在创建索引或集合时所使用的操作中指定相同的排序规则:
db.cities.find(
{ city: 'new york' }
).collation(
{ locale: 'en', strength: 2 }
);
这将返回“纽约”,“纽约”,“纽约”等。
db.zipcodes.find({city : "NEW YORK"}); // Case-sensitive
db.zipcodes.find({city : /NEW york/i}); // Note the 'i' flag for case-insensitivity
TL; DR
不要使用RegExp
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 }
]
)
需要在要搜索的任何TEXT字段上创建索引,而无需为查询建立索引将非常慢
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.company_profile.find({ "companyName" : { "$regex" : "Nilesh" , "$options" : "i"}});
$existing = Users::masterFind('all', ['conditions' => ['traits.0.email' => ['$regex' => "^$value$", '$options' => 'i']]]);
使用基于Regex的查询时要记住的一件非常重要的事情-在登录系统中执行此操作时,请转义要搜索的每个字符,并且不要忘记^和$运算符。Lodash为此提供了一个不错的功能,如果您已经在使用它的话:
db.stuff.find({$regex: new RegExp(_.escapeRegExp(bar), $options: 'i'})
为什么?假设有一个用户输入.*
为用户名。它将匹配所有用户名,只需猜测任何用户的密码即可启用登录。
最好的方法是选择语言,在为对象创建模型包装时,使save()方法遍历要搜索的一组字段,这些字段也会被索引;这些字段集应具有小写字母,然后用于搜索。
每次再次保存对象时,都将检查小写属性并使用对主属性的任何更改进行更新。这样一来,您就可以有效地进行搜索,但隐藏每次更新lc字段所需的额外工作。
小写的字段可以是key:value对象存储,也可以只是带有前缀lc_的字段名称。我使用第二种方法简化查询(深对象查询有时会令人困惑)。
注意:您要索引lc_字段,而不是它们基于的主要字段。
使用猫鼬对我有用:
var find = function(username, next){
User.find({'username': {$regex: new RegExp('^' + username, 'i')}}, function(err, res){
if(err) throw err;
next(null, res);
});
}
.toLowerCase()
如果指定不区分大小写的标志,这不是多余的i
吗?
聚合框架是在mongodb 2.2中引入的。您可以使用字符串运算符“ $ strcasecmp”在字符串之间进行不区分大小写的比较。比使用正则表达式更推荐和更容易。
这是有关聚合命令运算符的正式文档:https : //docs.mongodb.com/manual/reference/operator/aggregation/strcasecmp/#exp._S_strcasecmp。
您可以使用不区分大小写的索引:
下面的示例创建一个没有默认归类的集合,然后使用不区分大小写的归类在名称字段上添加索引。 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
db.users.createIndex( { name: 1 }, {collation: { locale: 'tr', strength: 2 } } )
搜索变量并转义:
const escapeStringRegexp = require('escape-string-regexp')
const name = 'foo'
db.stuff.find({name: new RegExp('^' + escapeStringRegexp(name) + '$', 'i')})
转义变量可以保护查询免受“。*”或其他正则表达式的攻击。
使用RegExp,以防万一其他选项对您不起作用,RegExp是个不错的选择。它使字符串不区分大小写。
var username = new RegExp("^" + "John" + "$", "i");;
在查询中使用用户名,然后完成。
我希望它也对您有用。祝一切顺利。
在C#中,使用过滤器对我有效。
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());
mongodb会认为p.Title.ToLower()是一个属性,无法正确映射。
对于任何使用Golang并希望使用mongodb和mgo godoc globalsign库进行区分大小写的全文本搜索的人。
collation := &mgo.Collation{
Locale: "en",
Strength: 2,
}
err := collection.Find(query).Collation(collation)
如您在mongo docs中所见-由于版本3.2 $text
索引默认情况下不区分大小写:https://docs.mongodb.com/manual/core/index-text/#text-index-case-insensitiveivity
这些已经过字符串搜索测试
{'_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
我遇到了类似的问题,这对我有用:
const flavorExists = await Flavors.findOne({
'flavor.name': { $regex: flavorName, $options: 'i' },
});
$regex
效率低下并且可能不安全,正如我在对其他2016年答案所做的编辑中所解释的那样。如果答案不再为社区服务,删除它们就不会感到羞耻!
$caseSensitive: false
。参见: docs.mongodb.org/manual/reference/operator/query/text/…–