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

And*_*ich 36 .net c# case-insensitive mongodb mongodb-.net-driver

我正在使用MongoDBMongoDBC#驱动程序.

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

我找到了一种方法:

Query.Matches(
    "FirstName", 
    BsonRegularExpression.Create(new Regex(searchKey,RegexOptions.IgnoreCase)));
Run Code Online (Sandbox Code Playgroud)

i3a*_*non 63

最简单和最安全的方法是使用Linq:

var names = namesCollection.AsQueryable().Where(name =>
    name.FirstName.ToLower().Contains("hamster"));
Run Code Online (Sandbox Code Playgroud)

正如解释的教程 ToLower,ToLowerInvariant,ToUpper并且ToUpperInvariant都在一个不区分大小写的方式进行比赛.之后,您可以使用所有支持的字符串方法,如ContainsStartsWith.

这个例子将生成:

{
    "FirstName" : /hamster/is
}
Run Code Online (Sandbox Code Playgroud)

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

  • 这应该是最好的答案! (3认同)
  • 有一个非常重要的细节,我花了几个小时才弄清楚:使用 Linq 时,不能使用 ToLower 和 Equals,必须使用“==”。即: .Where(x => x.Name.ToLower().Equals("fernando")) 抛出异常,而 .Where(x => x.Name.ToLower() == "fernando") 工作得很好! (2认同)

Mat*_*nty 38

我刚刚实现了比任何其他建议更简单的方法.但是我意识到由于这个问题的年龄,当时可能还没有这个功能.

使用Bson Regular Expression构造函数的选项传递不区分大小写.我刚看了一下源代码,发现'i'就是你所需要的.例如.

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

Query.Matches("MyField", bsonRegex);
Run Code Online (Sandbox Code Playgroud)

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

  • @bassbytesbikes你最好的选择是使用`Regex.Escape(filter)`来逃避`filter`中的字符然后传递它. (9认同)
  • 警告:如果传入的过滤器字符串包含正则表达式符号,则此操作将失败.例如,如果您传入电子邮件地址"john+smith@gmail.com",则由于"+"符号,它将返回0条记录. (4认同)

And*_*ich 16

尝试使用这样的东西:

Query.Matches("FieldName", BsonRegularExpression.Create(new Regex(searchKey, RegexOptions.IgnoreCase)))
Run Code Online (Sandbox Code Playgroud)

  • 使用/ ^ FirstName"$/i,上面的查询将匹配"WhateverFirstName" (4认同)

Thi*_*ilo 12

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

这种方法对许多数据库系统起作用(或必要),并且它应该比基于正则表达式的技术(至少对于前缀或精确匹配)执行得更好.


Tho*_*ann 5

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

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

代码:

var names = namesCollection.AsQueryable().Where(name =>
    name.FirstName.ToLower() == name.ToLower());
Run Code Online (Sandbox Code Playgroud)


ibe*_*dev 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/索引不区分大小写/了解更多详细信息

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

举个例子:

创建强度为 1 或 2 的排序规则,不区分大小写

private readonly Collation _caseInsensitiveCollation = new Collation("en", strength: CollationStrength.Primary);
Run Code Online (Sandbox Code Playgroud)

创建索引。就我而言,我索引了几个字段:

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);
}
Run Code Online (Sandbox Code Playgroud)

查询时请确保使用相同的排序规则:

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;
}
Run Code Online (Sandbox Code Playgroud)