var thename = 'Andrew';
db.collection.find({'name':thename});
Як мені зробити запит, що не враховує регістр? Я хочу знайти результат, навіть якщо "andrew";
var thename = 'Andrew';
db.collection.find({'name':thename});
Як мені зробити запит, що не враховує регістр? Я хочу знайти результат, навіть якщо "andrew";
Відповіді:
Рішення Кріса Фулстоу буде працювати (+1), однак воно може бути неефективним, особливо якщо ваша колекція дуже велика. Некореновані регулярні вирази (ті, що не починаються з ^
, що прив'язує регулярний вираз до початку рядка), і ті, хто використовує i
прапор для нечутливості до регістру, не використовуватимуть індекси, навіть якщо вони існують.
Альтернативним варіантом, який ви можете розглянути, є денормалізація даних для зберігання малої версії name
поля, наприклад як name_lower
. Потім ви можете ефективно запитувати (особливо якщо він індексується) для точних збігів, які не враховують регістр, таких як:
db.collection.find({"name_lower": thename.toLowerCase()})
Або з відповідним префіксом (вкорінений регулярний вираз) як:
db.collection.find( {"name_lower":
{ $regex: new RegExp("^" + thename.toLowerCase(), "i") } }
);
Обидва ці запити використовуватимуть індекс на name_lower
.
new RegExp('^'+ username + '$', "i")
щоб точно відповідати.
".*"
.
Вам потрібно буде використовувати для цього регулярний вираз, що не враховує регістр , наприклад
db.collection.find( { "name" : { $regex : /Andrew/i } } );
Для використання шаблону регулярного виразу з вашої thename
змінної побудуйте новий об’єкт RegExp :
var thename = "Andrew";
db.collection.find( { "name" : { $regex : new RegExp(thename, "i") } } );
Оновлення: Для точної відповідності слід використовувати регулярний вираз "name": /^Andrew$/i
. Завдяки Янніку Л.
name
, а не просто зрівняння.
{ "name": /^Andrew$/i }
Я вирішив це так.
var thename = 'Andrew';
db.collection.find({'name': {'$regex': thename,$options:'i'}});
Якщо ви хочете задати запит щодо "невідчутного до регістру точного відповідності", ви можете піти так.
var thename = '^Andrew$';
db.collection.find({'name': {'$regex': thename,$options:'i'}});
MongoDB 3.4 тепер включає можливість створити справжній індекс, що не враховує регістр, що різко збільшить швидкість пошуку без урахування регістру у великих наборах даних. Це виготовляється шляхом зазначення сортування міцністю 2.
Мабуть, найпростіший спосіб це зробити - встановити порівняння в базі даних. Тоді всі запити успадковують це порівняння і будуть використовувати його:
db.createCollection("cities", { collation: { locale: 'en_US', strength: 2 } } )
db.names.createIndex( { city: 1 } ) // inherits the default collation
Ви також можете зробити це так:
db.myCollection.createIndex({city: 1}, {collation: {locale: "en", strength: 2}});
І використовуйте його так:
db.myCollection.find({city: "new york"}).collation({locale: "en", strength: 2});
Це поверне міста з іменами "Нью-Йорк", "Нью-Йорк", "Нью-Йорк" тощо.
Для отримання додаткової інформації: https://jira.mongodb.org/browse/SERVER-90
З Mongoose (і Node) це спрацювало:
User.find({ email: /^name@company.com$/i })
User.find({ email: new RegExp(
`^ $ {emailVariable} $`, 'i')})
У MongoDB це спрацювало:
db.users.find({ email: { $regex: /^name@company.com$/i }})
Обидва рядки не враховують регістр. Електронна пошта в БД може бути, NaMe@CompanY.Com
і обидва рядки все одно знайдуть об’єкт у БД.
Так само ми могли б використовувати, /^NaMe@CompanY.Com$/i
і він все одно знаходив би електронну пошту: name@company.com
у БД.
Щоб знайти нечутливий рядок, використовуйте це,
var thename = "Andrew";
db.collection.find({"name":/^thename$/i})
Я щойно вирішив цю проблему кілька годин тому.
var thename = 'Andrew'
db.collection.find({ $text: { $search: thename } });
Ви навіть можете розширити це, вибравши потрібні поля з об'єкта користувача Ендрю, виконавши це таким чином:
db.collection.find({ $text: { $search: thename } }).select('age height weight');
Посилання: https://docs.mongodb.org/manual/reference/operator/query/text/#text
... з мангустом на NodeJS, який запитує:
const countryName = req.params.country;
{ 'country': new RegExp(`^${countryName}$`, 'i') };
або
const countryName = req.params.country;
{ 'country': { $regex: new RegExp(`^${countryName}$`), $options: 'i' } };
// ^australia$
або
const countryName = req.params.country;
{ 'country': { $regex: new RegExp(`^${countryName}$`, 'i') } };
// ^turkey$
Повний приклад коду в Javascript, NodeJS з Mongoose ORM на MongoDB
// get all customers that given country name
app.get('/customers/country/:countryName', (req, res) => {
//res.send(`Got a GET request at /customer/country/${req.params.countryName}`);
const countryName = req.params.countryName;
// using Regular Expression (case intensitive and equal): ^australia$
// const query = { 'country': new RegExp(`^${countryName}$`, 'i') };
// const query = { 'country': { $regex: new RegExp(`^${countryName}$`, 'i') } };
const query = { 'country': { $regex: new RegExp(`^${countryName}$`), $options: 'i' } };
Customer.find(query).sort({ name: 'asc' })
.then(customers => {
res.json(customers);
})
.catch(error => {
// error..
res.send(error.message);
});
});
Наступний запит знайде документи з необхідним рядком нечутливо, а також із глобальним входженням
db.collection.find({name:{
$regex: new RegExp(thename, "ig")
}
},function(err, doc) {
//Your code here...
});
Щоб знайти рядок літералів, що не враховує регістр:
db.collection.find({
name: {
$regex: new RegExp('^' + name.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '$', 'i')
}
});
db.collection.find({
name_lower: name.toLowerCase()
});
Регулярні вирази повільніші, ніж збіг буквальних рядків. Однак додаткове поле в нижньому регістрі збільшить складність коду. Якщо ви сумніваєтесь, використовуйте регулярні вирази. Я б запропонував використовувати явно поле малої літери, лише якщо воно може замінити ваше поле, тобто спочатку ви не дбаєте про регістр.
Зверніть увагу, що вам потрібно буде уникнути імені перед регулярним виразом. Якщо ви хочете ввести користувацькі символи підстановки, віддайте перевагу додаванню .replace(/%/g, '.*')
після екранування, щоб ви могли зіставити "a%", щоб знайти всі імена, що починаються з "a".
Ви можете використовувати нечутливі до регістру індекси :
У наступному прикладі створюється колекція без сортування за замовчуванням, а потім додається індекс до поля імені з урахуванням регістру. Міжнародні компоненти для 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
Найпростішим способом буде використання $ toLower, як показано нижче.
db.users.aggregate([
{
$project: {
name: { $toLower: "$name" }
}
},
{
$match: {
name: the_name_to_search
}
}
])