Пример:
> db.stuff.save({"foo":"bar"});
> db.stuff.find({"foo":"bar"}).count();
1
> db.stuff.find({"foo":"BAR"}).count();
0
Пример:
> db.stuff.save({"foo":"bar"});
> db.stuff.find({"foo":"bar"}).count();
1
> db.stuff.find({"foo":"BAR"}).count();
0
Вы можете использовать регулярное выражение .
В вашем примере это будет:
db.stuff.find( { foo: /^bar$/i } );
Я должен сказать, однако, возможно, вы могли бы просто уменьшить (или увеличить) значение на пути, а не нести дополнительные расходы каждый раз, когда вы их найдете. Очевидно, что это не сработает для имен людей и тому подобного, но, может быть, они используются как теги
ОБНОВЛЕНИЕ:
Первоначальный ответ устарел. Mongodb теперь поддерживает расширенный полнотекстовый поиск со многими функциями.
ОРИГИНАЛЬНЫЙ ОТВЕТ:
Следует отметить, что поиск с учетом регистра без учета регулярного выражения / i означает, что mongodb не может выполнять поиск по индексу, поэтому запросы к большим наборам данных могут занимать много времени.
Даже с небольшими наборами данных, это не очень эффективно. Вы получаете гораздо больший удар по процессору, чем ваш запрос, что может стать проблемой, если вы пытаетесь достичь масштаба.
В качестве альтернативы вы можете сохранить заглавную копию и выполнить поиск по ней. Например, у меня есть таблица User с именем пользователя в смешанном регистре, но id является копией имени пользователя в верхнем регистре. Это гарантирует, что дублирование с учетом регистра невозможно (наличие «Foo» и «foo» не будет разрешено), и я могу искать по id = username. toUpperCase (), чтобы получить регистрозависимый поиск имени пользователя.
Если ваше поле большого размера, например, тело сообщения, дублирование данных, вероятно, не является хорошим вариантом. Я считаю, что использование постороннего индексатора, такого как Apache Lucene, является лучшим вариантом в этом случае.
Имейте в виду, что предыдущий пример:
db.stuff.find( { foo: /bar/i } );
приведет к тому, что все записи, содержащие bar , будут соответствовать запросу (bar1, barxyz, openbar), это может быть очень опасно для поиска имени пользователя в функции auth. , ,
Вам может понадобиться, чтобы он совпадал только с поисковым термином, используя соответствующий синтаксис регулярного выражения:
db.stuff.find( { foo: /^bar$/i } );
См. http: // www. регулярные выражения. info / для получения справки по синтаксису для регулярных выражений
Если вам нужно создать регулярное выражение из переменной, это гораздо лучший способ сделать это: https: // stackoverflow. com / a / 10728069/309514
Затем вы можете сделать что-то вроде:
var string = "SomeStringToFind";
var regex = new RegExp(["^", string, "$"].join(""), "i");
// Creates a regex of: /^SomeStringToFind$/i
db.stuff.find( { foo: regex } );
Это дает преимущество в том, что вы программируете больше, или вы можете получить повышение производительности, заблаговременно скомпилировав его, если будете многократно его использовать.
По состоянию на Монгодб 3. 4 вы должны использовать регистр без учета регистра. Это самый быстрый способ выполнить поиск без учета регистра по наборам данных все большего размера. Я лично написал одному из основателей, чтобы он заработал, и он сделал это! (Это была проблема в JIRA около 5 лет, и многие просили эту функцию). Вот как это работает:
Индекс без учета регистра составляется путем указания параметров сортировки с силой 1 или 2. Вы можете создать регистр без учета регистра, как этот:
db.myCollection.createIndex({city: 1}, {collation: {locale: "en", strength: 2}});
Или вы можете сделать это для всей коллекции по умолчанию при создании базы данных следующим образом:
db.createCollection("Cities",{collation: {locale: "en",strength:2}});
И используйте это так:
db.myCollection.find({city: "new york"}).collation({locale: "en", strength: 2});
Это вернет "Нью-Йорк", "Нью-Йорк" и т. Д.
В качестве альтернативы, вы можете заставить все индексы использовать параметры сортировки по умолчанию при создании коллекции следующим образом:
db.createCollection("cities",{collation:{locale: "en", strength: 2}});
Преимущество этого метода - значительно улучшенная эффективность и скорость на больших наборах данных.
Для получения дополнительной информации: https: // jira. MongoDB. org / browse / SERVER-90 , https: // docs. MongoDB. ru / руководство / справка / сопоставление /
db.zipcodes.find({city : "NEW YORK"}); // Case-sensitive
db.zipcodes.find({city : /NEW york/i}); // Note the 'i' flag for case-insensitivity
TL; DR
Не использовать RegExp
Перейти естественным образом и использовать встроенную индексацию mongodb, поиск
db.articles.insert(
[
{ _id: 1, subject: "coffee", author: "xyz", views: 50 },
{ _id: 2, subject: "Coffee Shopping", author: "efg", views: 5 },
{ _id: 3, subject: "Baking a cake", author: "abc", views: 90 },
{ _id: 4, subject: "baking", author: "xyz", views: 100 },
{ _id: 5, subject: "Café Con Leche", author: "abc", views: 200 },
{ _id: 6, subject: "Сырники", author: "jkl", views: 80 },
{ _id: 7, subject: "coffee and cream", author: "efg", views: 10 },
{ _id: 8, subject: "Cafe con Leche", author: "xyz", views: 10 }
]
)
Необходимо создать индекс для любого поля ТЕКСТ , которое вы хотите найти, без индексации запрос будет очень медленным
db.articles.createIndex( { subject: "text" } )
db.articles.find( { $text: { $search: "coffee",$caseSensitive :true } } ) //FOR SENSITIVITY
db.articles.find( { $text: { $search: "coffee",$caseSensitive :false } } ) //FOR INSENSITIVITY
Использование Mongoose это сработало для меня:
var find = function(username, next){
User.find({'username': {$regex: new RegExp('^' + username, 'i')}}, function(err, res){
if(err) throw err;
next(null, res);
});
}
Одна очень важная вещь, которую следует иметь в виду при использовании запроса на основе Regex - когда вы делаете это для системы входа в систему, экранирует каждый отдельный символ , который вы ищете, и не забывайте операторы ^ и $. У Lodash есть хорошая функция для этого , если вы уже используете ее:
db.stuff.find({$regex: new RegExp(_.escapeRegExp(bar), $options: 'i'})
Почему? Представьте, что пользователь вводит .*
в качестве своего имени пользователя. Это будет соответствовать всем именам пользователей, позволяя войти в систему, просто угадав пароль любого пользователя.
Наилучший метод на выбранном вами языке - при создании обертки модели для ваших объектов, пусть ваш метод save () выполняет итерацию по набору полей, по которым вы будете искать, которые также проиндексированы; этот набор полей должен иметь строчные буквы, которые затем используются для поиска.
Каждый раз, когда объект сохраняется снова, свойства нижнего регистра проверяются и обновляются с любыми изменениями основных свойств. Это позволит вам эффективно выполнять поиск, но при этом каждый раз будет скрывать дополнительную работу, необходимую для обновления полей lc.
Строчные поля могут быть хранилищем объектов key: value или просто именем поля с префиксом lc_. Я использую второй для упрощения запросов (глубокие запросы к объектам могут иногда сбивать с толку).
Примечание: вы хотите индексировать поля lc_, а не основные поля, на которых они основаны.
Предположим, вы хотите выполнить поиск по «столбцу» в «Таблице» и хотите выполнить поиск без учета регистра. Лучший и эффективный способ, как показано ниже;
//create empty JSON Object
mycolumn = {};
//check if column has valid value
if(column) {
mycolumn.column = {$regex: new RegExp(column), $options: "i"};
}
Table.find(mycolumn);
Выше код просто добавляет значение поиска как RegEx и выполняет поиск с нечувствительными критериями, установленными с параметром «i».
Всего наилучшего.
Структура агрегации была введена в mongodb 2. 2 Вы можете использовать строковый оператор "$ strcasecmp" для сравнения строк без учета регистра. Это более рекомендуется и проще, чем использование регулярных выражений.
Вот официальный документ об операторе команды агрегации: https: // docs. MongoDB. ком / ручной / ссылки / оператор / агрегация / strcasecmp / # эксп. _S_strcasecmp .
db.company_profile.find({ "companyName" : { "$regex" : "Nilesh" , "$options" : "i"}});
Вы можете использовать регистров без учета регистра :
В следующем примере создается коллекция без сопоставления по умолчанию, затем добавляется индекс в поле имени с сопоставлением без учета регистра. Международные компоненты для Unicode
/* strength: CollationStrength.Secondary
* Secondary level of comparison. Collation performs comparisons up to secondary * differences, such as diacritics. That is, collation performs comparisons of
* base characters (primary differences) and diacritics (secondary differences). * Differences between base characters takes precedence over secondary
* differences.
*/
db.users.createIndex( { name: 1 }, collation: { locale: 'tr', strength: 2 } } )
Чтобы использовать индекс, запросы должны указывать одинаковое сопоставление.
db.users.insert( [ { name: "Oğuz" },
{ name: "oğuz" },
{ name: "OĞUZ" } ] )
// does not use index, finds one result
db.users.find( { name: "oğuz" } )
// uses the index, finds three results
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 2 } )
// does not use the index, finds three results (different strength)
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 1 } )
или вы можете создать коллекцию с сопоставлением по умолчанию:
db.createCollection("users", { collation: { locale: 'tr', strength: 2 } } )
db.users.createIndex( { name : 1 } ) // inherits the default collation
Для поиска и экранирования переменной:
const escapeStringRegexp = require('escape-string-regexp')
const name = 'foo'
db.stuff.find({name: new RegExp('^' + escapeStringRegexp(name) + '$', 'i')})
Экранирование переменной защищает запрос от атак с помощью '. * 'или другое регулярное выражение.
Использование фильтра работает для меня в C #.
string s = "searchTerm";
var filter = Builders.Filter.Where(p => p.Title.ToLower().Contains(s.ToLower()));
var listSorted = collection.Find(filter).ToList();
var list = collection.Find(filter).ToList();
Он может даже использовать индекс, потому что я считаю, что методы вызываются после возврата, но я еще не проверял это.
Это также позволяет избежать проблемы
var filter = Builders.Filter.Eq(p => p.Title.ToLower(), s.ToLower());
, что mongodb будет думать р. Заглавие. ToLower () является свойством и не будет отображаться правильно.
Использование RegExp , В случае, если какие-либо другие варианты не работают для вас, RegExp является хорошим вариантом. Это делает строку чувствительной к регистру.
var username = "John";
var uname = new RegExp(username, "i");
Значение uname
будет похоже на /John/i
.
использовать uname в запросах вместо имени пользователя, и тогда это сделано.
Я надеюсь, что это будет работать и для вас. Всего наилучшего.
Как вы можете видеть в документах Монго - начиная с версии 3. 2 Индекс $text
по умолчанию учитывает регистр: https: // docs. MongoDB. ru / manual / core / index-text / # text-index-case-insensitivity
Создайте текстовый индекс и используйте оператор $ text в вашем запросе .
Они были проверены на поиск строки
{'_id': /.*CM.*/} ||find _id where _id contains ->CM
{'_id': /^CM/} ||find _id where _id starts ->CM
{'_id': /CM$/} ||find _id where _id ends ->CM
{'_id': /.*UcM075237.*/i} ||find _id where _id contains ->UcM075237, ignore upper/lower case
{'_id': /^UcM075237/i} ||find _id where _id starts ->UcM075237, ignore upper/lower case
{'_id': /UcM075237$/i} ||find _id where _id ends ->UcM075237, ignore upper/lower case
Я столкнулся с подобной проблемой, и это то, что у меня сработало:
const flavorExists = await Flavors.findOne({
'flavor.name': { $regex: flavorName, $options: 'i' },
});
Я создал простой Func для регистра без учета регистра, который я использую в своем фильтре.
private Func CaseInsensitiveCompare = (field) =>
BsonRegularExpression.Create(new Regex(field, RegexOptions.IgnoreCase));
Затем вы просто фильтруете поле следующим образом.
db.stuff.find({"foo": CaseInsensitiveCompare("bar")}).count();