Как сделать запросы без учета регистра в Mongodb? - PullRequest
71 голосов
/ 18 августа 2011
var thename = 'Andrew';
db.collection.find({'name':thename});

Как сделать запрос без учета регистра? Я хочу найти результат, даже если "andrew";

Ответы [ 11 ]

98 голосов
/ 18 августа 2011

Решение Криса Фулстоу сработает (+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.

64 голосов
/ 18 августа 2011

Для этого нужно использовать регистронезависимое регулярное выражение , например,

db.collection.find( { "name" : { $regex : /Andrew/i } } );

Чтобы использовать шаблон регулярных выражений из переменной thename, создайте новый объект RegExp :

var thename = "Andrew";
db.collection.find( { "name" : { $regex : new RegExp(thename, "i") } } );

Обновление: Для точного соответствия следует использовать регулярное выражение "name": /^Andrew$/i. Благодаря Яннику Л.

25 голосов
/ 28 апреля 2016

Я решил это так.

 var thename = 'Andrew';
 db.collection.find({'name': {'$regex': thename,$options:'i'}});

Если вы хотите запросить «точное совпадение без учета регистра», то вы можете пойти так:

var thename =  '^Andrew$';
db.collection.find({'name': {'$regex': thename,$options:'i'}});
6 голосов
/ 01 декабря 2016

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

5 голосов
/ 28 января 2016

Я только что решил эту проблему несколько часов назад.

var thename = 'Andrew'
db.collection.find({ $text: { $search: thename } });
  • Для чувствительности к регистру и диакритической чувствительности по умолчанию задано значение false.

Вы даже можете расширить это, выбрав нужные поля в пользовательском объекте Эндрю, выполнив это следующим образом:

db.collection.find({ $text: { $search: thename } }).select('age height weight');

Ссылка: https://docs.mongodb.org/manual/reference/operator/query/text/#text

4 голосов
/ 15 октября 2018
  1. С Mongoose (и Node) это сработало:

    • User.find({ email: /^name@company.com$/i })

    • User.find({ email: new RegExp( `^ $ {emailVariable} $ `, 'i')})

  2. В MongoDB это работало:

    • db.users.find({ email: { $regex: /^name@company.com$/i }})

В обеих строках регистр не учитывается.Адрес электронной почты в БД может быть NaMe@CompanY.Com, и обе строки все равно найдут объект в БД.

Аналогично, мы можем использовать /^NaMe@CompanY.Com$/i, и он все равно найдет электронную почту: name@company.com в БД.

2 голосов
/ 03 октября 2018

Чтобы найти нечувствительную к регистру строку, используйте,

var thename = "Andrew";
db.collection.find({"name":/^thename$/i})
2 голосов
/ 12 августа 2017

Чтобы найти строку букв без учета регистра:

Использование регулярного выражения (рекомендуется)

db.collection.find({
    name: {
        $regex: new RegExp('^' + name.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '$', 'i')
    }
});

Использование индекса нижнего регистра (быстрее)

db.collection.find({
    name_lower: name.toLowerCase()
});

Регулярные выражениямедленнее, чем буквальное совпадение строк.Однако дополнительное строчное поле увеличит сложность вашего кода.В случае сомнений используйте регулярные выражения.Я бы предложил использовать явно поле нижнего регистра только в том случае, если оно может заменить ваше поле, т. Е. В первую очередь вас не волнует регистр.

Обратите внимание, что вам нужно будет экранировать имядо регулярного выражения.Если вы хотите, чтобы пользовательские символы ввода вводились пользователем, предпочитайте добавлять .replace(/%/g, '.*') после экранирования, чтобы можно было сопоставить «a%», чтобы найти все имена, начинающиеся с «a».

1 голос
/ 22 ноября 2017

Вы можете использовать Индексы без учета регистра :

В следующем примере создается коллекция без сопоставления по умолчанию, затем добавляется индекс в поле имени с сопоставлением без учета регистра. Международные компоненты для 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
1 голос
/ 28 ноября 2016

Следующий запрос найдет документы с необходимой строкой без учета регистра, а также с глобальным вхождением

db.collection.find({name:{
                             $regex: new RegExp(thename, "ig")
                         }
                    },function(err, doc) {
                                         //Your code here...
                  });
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...