我正在使用MongoDB和 MongoDB 的C# 驱动程序。
我最近发现 MongoDB 中的所有查询都是区分大小写的。如何进行不区分大小写的搜索?
我找到了一种方法来做到这一点:
Query.Matches(
"FirstName",
BsonRegularExpression.Create(new Regex(searchKey,RegexOptions.IgnoreCase)));
最简单和最安全的方法是使用Linq
:
var names = namesCollection.AsQueryable().Where(name =>
name.FirstName.ToLower().Contains("hamster"));
正如教程 ToLower
中所解释的ToLowerInvariant
,ToUpper
和ToUpperInvariant
都以不区分大小写的方式执行匹配。之后,您可以使用所有支持的字符串方法,例如Contains
or StartsWith
。
此示例将生成:
{
"FirstName" : /hamster/is
}
该i
选项使其不区分大小写。
我刚刚实现了这个比任何其他建议都简单得多。但是我意识到由于这个问题的年龄,这个功能当时可能不可用。
使用 Bson 正则表达式构造函数的选项传递不区分大小写。我刚刚查看了源代码,发现'i'就是你所需要的。例如。
var regexFilter = Regex.Escape(filter);
var bsonRegex = new BsonRegularExpression(regexFilter, "i");
Query.Matches("MyField", bsonRegex);
您不必为搜索保留两次记录。
尝试使用这样的东西:
Query.Matches("FieldName", BsonRegularExpression.Create(new Regex(searchKey, RegexOptions.IgnoreCase)))
您可能必须存储该字段两次,一次是使用其实际值,另一次是全部小写。然后,您可以查询小写版本以进行不区分大小写的搜索(不要忘记也将查询字符串小写)。
这种方法适用于(或者是必要的)许多数据库系统,并且它应该比基于正则表达式的技术表现更好(至少对于前缀或精确匹配)。
正如 i3arnon 回答的那样,您可以使用 Queryable 进行不区分大小写的比较/搜索。我发现,我不能使用 string.Equals() 方法,因为它不受支持。如果您需要进行比较,很遗憾 Contains() 不合适,这让我在很长一段时间内一直在努力寻找解决方案。
对于任何想要进行字符串比较的人,只需使用 == 而不是 .Equals()。
代码:
var names = namesCollection.AsQueryable().Where(name =>
name.FirstName.ToLower() == name.ToLower());
您还可以使用 MongoDB 的内置过滤器。它可能使使用 mongo 的某些方法更容易。
var filter = Builders<Model>.Filter.Where(p => p.PropertyName.ToLower().Contains(s.ToLower()));
var list = collection.Find(filter).Sort(mySort).ToList();
对于 MongoDB 3.4+,推荐的方法是使用索引。见https://jira.mongodb.org/browse/DOCS-11105?focusedCommentId=1859745&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-1859745
我通过以下方式成功搜索不区分大小写:1.使用排序规则为区域设置(例如:“en”)创建索引,强度为 1 或 2。请参阅https://docs.mongodb.com/manual/core/索引不区分大小写/了解更多详情
举个例子:
创建强度为 1 或 2 的排序规则以不区分大小写
private readonly Collation _caseInsensitiveCollation = new Collation("en", strength: CollationStrength.Primary);
创建索引。就我而言,我索引了几个字段:
private void CreateIndex()
{
var indexOptions = new CreateIndexOptions {Collation = _caseInsensitiveCollation};
var indexDefinition
= Builders<MyDto>.IndexKeys.Combine(
Builders<MyDto>.IndexKeys.Ascending(x => x.Foo),
Builders<MyDto>.IndexKeys.Ascending(x => x.Bar));
_myCollection.Indexes.CreateOne(indexDefinition, indexOptions);
}
查询时确保使用相同的排序规则:
public IEnumerable<MyDto> GetItems()
{
var anyFilter = GetQueryFilter();
var anySort = sortBuilder.Descending(x => x.StartsOn);
var findOptions = new FindOptions {Collation = _caseInsensitiveCollation};
var result = _salesFeeRules
.Find(anyFilter, findOptions)
.Sort(anySort)
.ToList();
return result;
}
如果其他人想知道,使用fluent-mongo插件,您可以使用 Linq 进行如下查询:
public User FindByEmail(Email email)
{
return session.GetCollection<User>().AsQueryable()
.Where(u => u.EmailAddress.ToLower() == email.Address.ToLower()).FirstOrDefault();
}
这会导致正确的 JS 查询。不幸的是,尚不支持 String.Equals()。
MongoDB 3.4+ 最简单的方法是使用 ICU 比较级别之一
return await Collection()
.Find(filter, new FindOptions { Collation = new Collation("en", strength: CollationStrength.Primary) })
.ToListAsync();
更多信息https://docs.mongodb.com/manual/reference/method/cursor.collation/index.html
一种方法是使用 MongoDB.Bson.BsonJavaScript 类,如下所示
store.FindAs<Property>(Query.Where(BsonJavaScript.Create(string.Format("this.City.toLowerCase().indexOf('{0}') >= 0", filter.City.ToLower()))));
这是精确的文本搜索且不区分大小写(请参阅此链接)。
{ “FieldName” : /^keywordHere$/i }