MongoDB и C #: поиск без учета регистра - PullRequest
36 голосов
/ 16 декабря 2010

Я использую MongoDB и драйвер C # для MongoDB .

Недавно я обнаружил, что все запросы в MongoDB чувствительны к регистру.Как мне выполнить поиск без учета регистра?

Я нашел один способ сделать это:

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

Ответы [ 10 ]

62 голосов
/ 23 января 2014

Самый простой и безопасный способ сделать это - использовать Linq:

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

Как объяснено в учебнике ToLower, ToLowerInvariant, ToUpper и ToUpperInvariant, все сопоставления выполняются без учета регистра. После этого вы можете использовать все поддерживаемые строковые методы, такие как Contains или StartsWith.

Этот пример сгенерирует:

{
    "FirstName" : /hamster/is
}

Опция i делает его нечувствительным к регистру.

37 голосов
/ 26 марта 2013

Я только что реализовал это намного проще, чем любое другое предложение.Однако я понимаю, что из-за возраста этого вопроса эта функциональность может быть недоступна в то время.

Используйте параметры конструктора регулярных выражений Bson для передачи без учета регистра.Я только что посмотрел на исходный код и обнаружил, что «я» это все, что вам нужно.Например.

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

Query.Matches("MyField", bsonRegex);

Вам не нужно вести записи дважды для поиска.

16 голосов
/ 16 декабря 2010

попробуйте использовать что-то вроде этого:

Query.Matches("FieldName", BsonRegularExpression.Create(new Regex(searchKey, RegexOptions.IgnoreCase)))
12 голосов
/ 16 декабря 2010

Вероятно, вам придется хранить поле дважды, один раз с его реальным значением и снова со всеми строчными буквами. Затем вы можете запросить версию в нижнем регистре для поиска без учета регистра (не забудьте также в нижнем регистре строку запроса).

Этот подход работает (или необходим) для многих систем баз данных и должен работать лучше, чем методы на основе регулярных выражений (по крайней мере, для префикса или точного сопоставления).

4 голосов
/ 20 мая 2016

Как ответил i3arnon, вы можете использовать Queryable для сравнения / поиска без учета регистра. Я обнаружил, что не могу использовать метод string.Equals (), потому что он не поддерживается. Если вам нужно сделать сравнение, Contains (), к сожалению, не подойдет, что удерживало меня в борьбе за решение в течение достаточно долгого времени

Если вы хотите сравнить строки, просто используйте == вместо .Equals ().

Код:

var names = namesCollection.AsQueryable().Where(name =>
    name.FirstName.ToLower() == name.ToLower());
1 голос
/ 08 августа 2017

Вы также можете использовать встроенные фильтры MongoDB.Это может облегчить использование некоторых методов Монго.

var filter = Builders<Model>.Filter.Where(p => p.PropertyName.ToLower().Contains(s.ToLower()));
var list = collection.Find(filter).Sort(mySort).ToList();
1 голос
/ 26 июля 2011

Если кому-то еще интересно, используя дополнение 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 голосов
/ 23 октября 2018

это точный текстовый поиск и без учета регистра (см. эту ссылку ).

{ “FieldName” : /^keywordHere$/i }
0 голосов
/ 10 июня 2018

Для 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;
}
0 голосов
/ 16 февраля 2013

Способ сделать это - использовать класс MongoDB.Bson.BsonJavaScript, как показано ниже

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