MongoDB 和 C#:不区分大小写的搜索

问题描述 投票:0回答:12

我正在使用 MongoDBMongoDB 的 C# 驱动程序

我最近发现 MongoDB 中的所有查询都是区分大小写的。如何进行不区分大小写的搜索?

我找到了一种方法:

Query.Matches(
    "FirstName", 
    BsonRegularExpression.Create(new Regex(searchKey,RegexOptions.IgnoreCase)));
c# .net mongodb mongodb-.net-driver case-insensitive
12个回答
75
投票

最简单、最安全的方法是使用

Linq
:

var names = namesCollection.AsQueryable().Where(name =>
    name.FirstName.ToLower().Contains("hamster"));

教程中所述,

ToLower
ToLowerInvariant
ToUpper
ToUpperInvariant
都以不区分大小写的方式执行匹配。之后,您可以使用所有支持的字符串方法,例如
Contains
StartsWith

此示例将生成:

{
    "FirstName" : /hamster/is
}

i
选项使其不区分大小写。


47
投票

我刚刚实现的这个比任何其他建议都简单得多。然而我意识到由于这个问题的年龄,这个功能当时可能不可用。

使用 Bson 正则表达式构造函数的选项来传递不区分大小写的情况。我刚刚查看了源代码,发现“i”就是您所需要的。例如。

var regexFilter = Regex.Escape(filter);
var bsonRegex = new BsonRegularExpression(regexFilter, "i");

Query.Matches("MyField", bsonRegex);

您不必为了搜索而保留两次记录。


17
投票

尝试使用这样的东西:

Query.Matches("FieldName", BsonRegularExpression.Create(new Regex(searchKey, RegexOptions.IgnoreCase)))

12
投票

您可能需要将该字段存储两次,一次使用其实际值,另一次全部使用小写。然后,您可以查询小写版本以进行不区分大小写的搜索(不要忘记也将查询字符串小写)。

这种方法对于许多数据库系统都有效(或者是必要的),并且它应该比基于正则表达式的技术表现得更好(至少对于前缀或精确匹配)。


7
投票

正如 i3arnon 回答的那样,您可以使用 Queryable 进行不区分大小写的比较/搜索。我发现我无法使用 string.Equals() 方法,因为它不受支持。如果您需要进行比较,不幸的是 Contains() 不适合,这让我在相当长的一段时间内一直在寻找解决方案。

对于任何想要进行字符串比较的人,只需使用 == 而不是 .Equals()。

代码:

var names = namesCollection.AsQueryable().Where(name =>
    name.FirstName.ToLower() == name.ToLower());

5
投票

对于 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/index-case-insensitive/ 了解更多信息更多详情

  1. 在 MongoDb 集合上执行搜索时使用相同的排序规则。

举个例子:

创建强度为 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;
}

4
投票

您还可以使用 MongoDB 的内置过滤器。它可能会让使用 mongo 的一些方法变得更容易。

var filter = Builders<Model>.Filter.Where(p => p.PropertyName.ToLower().Contains(s.ToLower()));
var list = collection.Find(filter).Sort(mySort).ToList();

2
投票

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


1
投票

如果其他人想知道,使用 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()。


0
投票

一种方法是使用 MongoDB.Bson.BsonJavaScript 类,如下所示

 store.FindAs<Property>(Query.Where(BsonJavaScript.Create(string.Format("this.City.toLowerCase().indexOf('{0}') >= 0", filter.City.ToLower()))));

0
投票

这个对我有用(适用于

MongoDB.Driver
2.22.0+ 版本)

Builders<TEntity>.Filter
.Regex(e => e.FirstName, new BsonRegularExpression($".*{value}.*", "i"))

我还建议将

"i"
移至常量,如
BsonRegularExpressionOptions.IgnoreCase


-1
投票

这是精确的文本搜索,不区分大小写(请参阅此链接)。

{ “FieldName” : /^keywordHere$/i }
© www.soinside.com 2019 - 2024. All rights reserved.