MongoDB и C#: поиск без учета регистра
Я использую MongoDB и драйвер C# для MongoDB.
недавно я обнаружил, что все запросы в MongoDB чувствительны к регистру. Как я могу сделать поиск без учета регистра?
Я нашел один способ сделать это:
Query.Matches(
"FirstName",
BsonRegularExpression.Create(new Regex(searchKey,RegexOptions.IgnoreCase)));
9 ответов
самый простой и безопасный способ сделать это с помощью Linq
:
var names = namesCollection.AsQueryable().Where(name =>
name.FirstName.ToLower().Contains("hamster"));
как поясняется в учебник ToLower
, ToLowerInvariant
, ToUpper
и ToUpperInvariant
все выполняют матчи нечувствительным к регистру способом. После этого вы можете использовать все поддерживаемые строковые методы, такие как Contains
или StartsWith
.
этот пример будет генерировать:
{
"FirstName" : /hamster/is
}
на делает его нечувствительным к регистру.
Я просто реализовано это намного проще, чем любые другие предложения. Однако я понимаю, что из-за возраста этого вопроса эта функциональность, возможно, не была доступна в то время.
используйте параметры конструктора регулярных выражений Bson для передачи нечувствительности к регистру. Я просто взглянул на исходный код и обнаружил, что " я " - это все, что вам нужно. Например.
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 для выполнения сравнения/поиска без учета регистра. Я обнаружил, что не могу использовать веревку.Метод Equals (), потому что он не поддерживается. Если вам нужно сделать сравнение, Contains (), к сожалению, не подходит, что заставило меня бороться за решение в течение довольно долгого времени.
для тех, кто хочет сделать сравнение строк, просто используйте == вместо .Равняется.)(
код:
var names = namesCollection.AsQueryable().Where(name =>
name.FirstName.ToLower() == name.ToLower());
в случае, если кто-то еще задается вопросом, используя свободно-монго add-on, вы можете использовать Linq для запроса:
public User FindByEmail(Email email)
{
return session.GetCollection<User>().AsQueryable()
.Where(u => u.EmailAddress.ToLower() == email.Address.ToLower()).FirstOrDefault();
}
что приводит к правильному JS-запросу. К Сожалению, Стринг.Equals () пока не поддерживается.
вы также можете использовать встроенные фильтры MongoDB. Это может облегчить использование некоторых методов монго.
var filter = Builders<Model>.Filter.Where(p => p.PropertyName.ToLower().Contains(s.ToLower()));
var list = collection.Find(filter).Sort(mySort).ToList();
способ сделать это-использовать MongoDB.Бсына.Класс BsonJavaScript, как показано ниже
store.FindAs<Property>(Query.Where(BsonJavaScript.Create(string.Format("this.City.toLowerCase().indexOf('{0}') >= 0", filter.City.ToLower()))));
для MongoDB 3.4+ рекомендуется использовать индексы. Смотри https://jira.mongodb.org/browse/DOCS-11105?focusedCommentId=1859745&page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel#comment-1859745
я успешно ищу с нечувствительным к регистру: 1. Создание индекса с параметрами сортировки для локали (e.g: "en") и с силой 1 или 2. См.https://docs.mongodb.com/manual/core/index-case-insensitive/ для дальнейшего подробности
- использование тех же параметров сортировки при выполнении поиска в коллекции 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;
}