Пример:
> 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
Вы можете использовать regex.
В вашем примере это будет:
db.stuff.find( { foo: /^bar$/i } );
Я должен сказать, хотя, может быть, вы могли бы просто изменить (или высвободить) значение на пути, а не приносить дополнительную стоимость каждый раз, когда найдете его. Очевидно, что это не будет работать для имен людей и т.д., Но, возможно, для использования в виде тегов.
UPDATE:
Оригинальный ответ теперь устарел. Mongodb теперь поддерживает расширенный полнотекстовый поиск со многими функциями.
ОРИГИНАЛЬНЫЙ ОТВЕТ:
Следует отметить, что поиск с регистрозависимым регистром нечувствителен /i означает, что mongodb не может искать по индексу, поэтому запросы к большим наборам данных могут занять много времени.
Даже с небольшими наборами данных он не очень эффективен. Вы получаете гораздо больший хит процессора, чем ваши ордера на запрос, что может стать проблемой, если вы пытаетесь достичь масштаба.
В качестве альтернативы вы можете сохранить заглавную копию и выполнить поиск по ней. Например, у меня есть таблица User, у которой есть имя пользователя, которое является смешанным случаем, но идентификатор является заглавной копией имени пользователя. Это гарантирует, что дублирование с учетом регистра невозможно (наличие "Foo" и "foo" не будет разрешено), и я могу выполнить поиск по id = username.toUpperCase(), чтобы получить поиск по имени пользователя без учета регистра.
Если ваше поле большое, например тело сообщения, дублирование данных, вероятно, не является хорошим вариантом. Я считаю, что использование альтернативного индексатора, такого как Apache Lucene, является лучшим вариантом в этом случае.
Имейте в виду, что предыдущий пример:
db.stuff.find( { foo: /bar/i } );
приведет к тому, что каждая запись, содержащая бар, будет соответствовать запросу (bar1, barxyz, openbar), это может быть очень опасно для поиска имени пользователя в функции auth...
Возможно, вам потребуется сопоставить только поисковый запрос, используя соответствующий синтаксис regexp как:
db.stuff.find( { foo: /^bar$/i } );
См. http://www.regular-expressions.info/ для справки по синтаксису для регулярных выражений
Если вам нужно создать regexp из переменной, это гораздо лучший способ сделать это: fooobar.com/questions/31035/...
Затем вы можете сделать что-то вроде:
var string = "SomeStringToFind";
var regex = new RegExp(["^", string, "$"].join(""), "i");
// Creates a regex of: /^SomeStringToFind$/i
db.stuff.find( { foo: regex } );
Это имеет преимущество быть более программным, или вы можете получить повышение производительности путем компиляции его заранее, если вы многократно используете его.
Начиная с MongoDB, рекомендуемый способ выполнения быстрого поиска без учета регистра - это использование индекса без учета регистра.
Я лично написал одному из основателей, чтобы он заработал, и он сделал это! Это была проблема JIRA с 2009 года, и многие просили эту функцию. Вот как это работает:
Индекс без учета регистра создается путем указания параметров сортировки с силой 1 или 2. Вы можете создать индекс без учета регистра, например так:
db.cities.createIndex(
{ city: 1 },
{
collation: {
locale: 'en',
strength: 2
}
}
);
Вы также можете указать параметры сортировки по умолчанию для каждой коллекции:
db.createCollection('cities', { collation: { locale: 'en', strength: 2 } } );
В любом случае, чтобы использовать индекс без учета регистра, вам нужно указать тот же порядок сортировки в операции find
которая использовалась при создании индекса или коллекции:
db.cities.find(
{ city: 'new york' }
).collation(
{ locale: 'en', strength: 2 }
);
Это вернет "Нью-Йорк", "Нью-Йорк", "Нью-Йорк" и т.д.
username: 'bill'
соответствие BILL
или Bill
, а не поисковый запрос полного текста, который будет также соответствовать стеблям слова bill
, таким как Bills
, billed
и т.д.Ответы, предлагающие использовать регулярные выражения, являются медленными, потому что даже с индексами документация гласит:
"Запросы регулярного выражения без учета регистра обычно не могут эффективно использовать индексы. Реализация $ regex не учитывает параметры сортировки и не может использовать индексы без учета регистра".
Ответы $regex
также рискуют ввести пользовательский ввод.
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
Go natural И использовать встроенную индексацию 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
db.company_profile.find({ "companyName" : { "$regex" : "Nilesh" , "$options" : "i"}});
Mongo (текущая версия 2.0.0) не разрешает поиск по регистровым полям с индексированными полями - см. их документацию. Для неиндексированных полей регулярные выражения, перечисленные в других ответах, должны быть точными.
Лучший способ заключается в выборе вашего языка при создании обертки модели для ваших объектов, попробуйте выполнить метод save() через набор полей, которые вы будете искать, которые также индексируются; эти группы полей должны иметь строчные копии, которые затем используются для поиска.
Каждый раз, когда объект снова сохраняется, свойства нижнего регистра затем проверяются и обновляются с любыми изменениями основных свойств. Это позволит вам эффективно искать, но скрыть дополнительную работу, необходимую для обновления полей lc каждый раз.
Поля нижнего регистра могут быть хранилищем объектов ключа: значение или просто имя поля с префиксом lc_. Я использую второй, чтобы упростить запрос (запросы на глубинные объекты иногда могут сбивать с толку).
Примечание: вы хотите индексировать поля lc_, а не основные поля, на которых они основаны.
Используя Mongoose, это сработало для меня:
var find = function(username, next){
User.find({'username': {$regex: new RegExp('^' + username, 'i')}}, function(err, res){
if(err) throw err;
next(null, res);
});
}
Предположим, что вы хотите найти "столбец" в "Таблице", и вы хотите, чтобы поиск в insensstive. Лучший и эффективный способ, как показано ниже:
//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 и выполняется поиск с использованием критериев insensitve, установленных с опцией "i".
Все самое лучшее.
Одна важная вещь, которую следует иметь в виду при использовании запроса на основе Regex. Когда вы делаете это для системы входа в систему, избегайте каждого символа, который вы ищете, и не забывайте операторы ^ и $. У Lodash есть хорошая функция для этого, если вы уже используете его:
db.stuff.find({$regex: new RegExp(_.escapeRegExp(bar), $options: 'i'})
Почему? Представьте, что пользователь вводит .*
в качестве своего имени пользователя. Это будет соответствовать всем именам пользователей, что позволит войти в систему, просто угадывая пароль пользователя.
Структура агрегации была введена в mongodb 2.2. Вы можете использовать строковый оператор "$ strcasecmp", чтобы сделать нечувствительное к регистру сравнение строк. Это более рекомендуется и проще, чем при использовании регулярного выражения.
Здесь официальный документ оператора оператора агрегации: https://docs.mongodb.com/manual/reference/operator/aggregation/strcasecmp/#exp._S_strcasecmp.
Вы можете использовать Нечувствительные к регистру индексы:
В следующем примере создается коллекция без сортировки по умолчанию, а затем добавляется индекс в поле имени с учетом нечувствительности к регистру. Международные компоненты для Юникода
/* 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')})
Выход из переменной защищает запрос от атак с помощью '. *' Или другого регулярного выражения.
Я создал простой Func для нечувствительного к регистру регулярного выражения, которое я использую в своем фильтре.
private Func<string, BsonRegularExpression> CaseInsensitiveCompare = (field) =>
BsonRegularExpression.Create(new Regex(field, RegexOptions.IgnoreCase));
Затем вы просто фильтруете поле в следующем виде.
db.stuff.find({"foo": CaseInsensitiveCompare("bar")}).count();
Использование фильтра работает для меня на С#.
string s = "searchTerm";
var filter = Builders<Model>.Filter.Where(p => p.Title.ToLower().Contains(s.ToLower()));
var listSorted = collection.Find(filter).ToList();
var list = collection.Find(filter).ToList();
Он может даже использовать индекс, потому что я считаю, что методы вызываются после того, как произойдет возврат, но я еще не тестировал это.
Это также позволяет избежать проблемы
var filter = Builders<Model>.Filter.Eq(p => p.Title.ToLower(), s.ToLower());
что mongodb будет думать, что p.Title.ToLower() является свойством и не будет правильно отображаться.
Используйте RegExp, в случае, если какие-либо другие варианты не работают для вас, RegExp является хорошим вариантом. Это делает строку нечувствительной к регистру.
var username = new RegExp("^" + "John" + "$", "i");;
использовать имя пользователя в запросах, а затем все готово.
Я надеюсь, что это сработает и для вас. Всего наилучшего.
Для любого, кто использует Golang и хочет иметь полнотекстовый поиск с учетом регистра с помощью mongodb и библиотеки globalsign mgo godoc.
collation := &mgo.Collation{
Locale: "en",
Strength: 2,
}
err := collection.Find(query).Collation(collation)
Как вы можете видеть в mongo docs - поскольку версия 3.2 $text
по умолчанию не учитывает регистр: https://docs.mongodb.com/manual/core/index-text/#text-index-case-insensitivity
Создать текстовый индекс и использовать $text operator в вашем запрос.
Они были протестированы для поиска строк
{'_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' },
});