例子:
> db.stuff.save({"foo":"bar"});
> db.stuff.find({"foo":"bar"}).count();
1
> db.stuff.find({"foo":"BAR"}).count();
0
例子:
> 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 } );
不过,我必须说,也许您可以在途中降低(或提高)价值,而不是每次找到它时都会产生额外的成本。显然,这不适用于人名等,但可能适用于标签等用例。
更新:
原来的答案现在已经过时了。Mongodb 现在支持高级全文搜索,具有许多功能。
原始答案:
需要注意的是,使用正则表达式不区分大小写 /i 进行搜索意味着 mongodb 无法按索引进行搜索,因此针对大型数据集的查询可能需要很长时间。
即使使用小数据集,它也不是很有效。您的 CPU 命中率远高于查询保证,如果您试图实现规模化,这可能会成为一个问题。
作为替代方案,您可以存储大写副本并对其进行搜索。例如,我有一个用户表,其中包含混合大小写的用户名,但 id 是用户名的大写副本。这确保了区分大小写的重复是不可能的(不允许同时使用“Foo”和“foo”),并且我可以通过 id = username.toUpperCase() 进行搜索以获得对用户名的不区分大小写的搜索。
如果您的字段很大,例如消息正文,则复制数据可能不是一个好的选择。我相信在这种情况下使用像 Apache Lucene 这样的外部索引器是最好的选择。
从 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 }
);
这将返回“纽约”、“纽约”、“纽约”等。
如果您需要从变量创建正则表达式,这是一种更好的方法: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 } );
这样做的好处是更加程序化,或者如果您经常重用它,您可以通过提前编译它来提高性能。
请记住前面的示例:
db.stuff.find( { foo: /bar/i } );
将导致包含bar的每个条目都匹配查询( bar1、barxyz、openbar ),这对于在 auth 函数上搜索用户名可能非常危险......
您可能需要使用适当的正则表达式语法使其仅匹配搜索词:
db.stuff.find( { foo: /^bar$/i } );
有关正则表达式的语法帮助,请参见http://www.regular-expressions.info/
db.company_profile.find({ "companyName" : { "$regex" : "Nilesh" , "$options" : "i"}});
db.zipcodes.find({city : "NEW YORK"}); // Case-sensitive
db.zipcodes.find({city : /NEW york/i}); // Note the 'i' flag for case-insensitivity
TL;博士
不要使用正则表达式
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
使用基于正则表达式的查询时要记住的一件非常重要的事情 - 当您为登录系统执行此操作时,请转义您正在搜索的每个字符,并且不要忘记 ^ 和 $ 运算符。Lodash 有一个很好的功能,如果你已经在使用它:
db.stuff.find({$regex: new RegExp(_.escapeRegExp(bar), $options: 'i'})
为什么?想象一个用户.*
作为他的用户名输入。这将匹配所有用户名,只需猜测任何用户的密码即可登录。
Mongo(当前版本 2.0.0)不允许对索引字段进行不区分大小写的搜索 - 请参阅他们的文档。对于非索引字段,其他答案中列出的正则表达式应该没问题。
假设您要在“表格”中搜索“列”并且您想要不区分大小写的搜索。最好和最有效的方法是:
//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”作为选项设置的不敏感条件进行搜索。
用于搜索变量并将其转义:
const escapeStringRegexp = require('escape-string-regexp')
const name = 'foo'
db.stuff.find({name: new RegExp('^' + escapeStringRegexp(name) + '$', '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);
});
}
聚合框架是在 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
我很惊讶没有人通过使用/^bar$/i
if bar是密码或帐户 ID 搜索来警告正则表达式注入的风险。( bar => .*@myhackeddomain.com
例如,我敢打赌:使用\Q
\E
正则表达式特殊字符!在 PERL 中提供
db.stuff.find( { foo: /^\Qbar\E$/i } );
您应该转义bar变量\
字符\\
以避免\E
再次利用,例如bar = '\E.*@myhackeddomain.com\Q'
另一种选择是使用正则表达式转义字符策略,如此处描述的Javascript 等效于 Perl 的 \Q ... \E 或 quotemeta()
使用RegExp,如果任何其他选项不适合您,RegExp 是一个不错的选择。它使字符串不区分大小写。
var username = new RegExp("^" + "John" + "$", "i");;
在查询中使用用户名,然后完成。
我希望它也对你有用。祝一切顺利。
如果您使用的是 MongoDB Compass:
转到集合,在过滤器类型中 -> {Fieldname: /string/i}
对于使用 Mongoose 的 Node.js:
Model.find({FieldName: {$regex: "stringToSearch", $options: "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() 是一个属性,不会正确映射。
我遇到了类似的问题,这对我有用:
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));
然后,您只需按如下方式过滤字段。
db.stuff.find({"foo": CaseInsensitiveCompare("bar")}).count();
这些已针对字符串搜索进行了测试
{'_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
对于任何使用 Golang 并希望使用 mongodb 和mgo godoc globalsign library进行区分大小写的全文搜索的人。
collation := &mgo.Collation{
Locale: "en",
Strength: 2,
}
err := collection.Find(query).Collation(collation)
正如您在 mongo 文档中看到的那样 - 因为版本 3.2$text
索引默认情况下不区分大小写:https ://docs.mongodb.com/manual/core/index-text/#text-index-case-insensitive