Как сделать запрос MongoDB с «лайком»?


1438

Я хочу запросить что-то с likeзапросом SQL :

SELECT * FROM users  WHERE name LIKE '%m%'

Как мне добиться того же в MongoDB? Я не могу найти оператора likeв документации .


7
см. документы mongodb: расширенные запросы - регулярные выражения mongodb.org/display/DOCS/…
douyw

7
Ваш вопрос имеет по крайней мере 5голоса для тега like-operator . Могу ли я попросить вас предложить sql-like как синоним ?
Кермит,

3
Эта ссылка может помочь вам goo.gl/gdTYK8
Дилип Кр Сингх

Ответы:


1945

Это должно быть:

db.users.find({"name": /.*m.*/})

или похожие:

db.users.find({"name": /m/})

Вы ищете что-то, что где-то содержит "m" (оператор SQL ' %' эквивалентен ' .*' регулярного выражения '), а не то, что "m" привязано к началу строки.

примечание: mongodb использует регулярные выражения, которые являются более мощными, чем "LIKE" в sql. С помощью регулярных выражений вы можете создать любой шаблон, который вы себе представляете.

Для получения дополнительной информации о регулярных выражениях обратитесь к этой ссылке https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions


96
дорогой поиск по регулярному выражению?
Freewind

147
На самом деле, это зависит. Если запрос не использует индекс и должен выполнить сканирование таблицы, то он, безусловно, может быть дорогим. Если вы выполняете запрос регулярного выражения «начинается с», то для этого можно использовать индекс. Лучше всего запустить объяснение (), чтобы увидеть, что происходит.
Кайл Банкер

35
Когда он не привязан к началу строки, это несколько дорого. Но опять же, как и LIKEзапрос в SQL.
Эмили

4
так что, пока он привязан к началу строки, все в порядке? круто тогда. значит ли это, что нам нужно добавить ^
user4951

44
Я хотел бы добавить регулярное выражение яjavascript db.users.find({ "name": { $regex: /m/i } })
Дорон Сигал

368
db.users.insert({name: 'paulo'})
db.users.insert({name: 'patric'})
db.users.insert({name: 'pedro'})

db.users.find({name: /a/})  //like '%a%'

выход: Пауло, Патрик

db.users.find({name: /^pa/}) //like 'pa%' 

выход: Пауло, Патрик

db.users.find({name: /ro$/}) //like '%ro'

выход: педро


хороший пример! Я считаю, что проверка заканчивается пробелом и нашел это :) / $ /
Phuong

как вы находите все записи по имени? или подстановочный знак для * в SQL? Что-то, что делает, select name from users;что просто перечисляет всех пользователей?
anon58192932

1
@ anon58192932 Чтобы отобразить все записи только поля «имя» в таблице с именем «пользователи», вы можете использовать метод project (), задав значения полей, которые вы хотите равными 1. Поля, которые не упомянуты в project (), не будут Получено, кроме _id. Поле _id выводится по умолчанию, что можно подавить, указав значение 0 для _id внутри метода project (). Что-то вроде - db.collection.find (). Project ({name: 1, _id: 0}) .toArray (function (err, docs) {console.log (docs); обратный вызов (docs);}); Порекомендуйте
gauravparmar

282

В

  • PyMongo с использованием Python
  • Мангуст используя Node.js
  • Джонго , использующий Java
  • MGO , используя Go

ты можешь сделать:

db.users.find({'name': {'$regex': 'sometext'}})

2
он работает нормально для поиска с учетом регистра, подскажите, пожалуйста, как я могу заставить его выполнять поиск без учета регистра?
Таир Ясин

Для чего будет регулярное выражение%sometext%
Тахир Ясин

64
@TahirYasin, если вам все еще интересно, поиск без db.users.find({'name': {'$regex': 'sometext', '$options': 'i'}})
учета

Я решил в golang, используя mgo просто код, подобный этому, селектор: = bson.M {"technician": bson.M {"$ regex": tech}}
Сандун Приянка,

1
Чувствую, что это должен быть принятый ответ. Это самый простой и самый элегантный в настоящее время.
Brett84c

88

В PHP вы можете использовать следующий код:

$collection->find(array('name'=> array('$regex' => 'm'));

4
python + mongoengine: people = People.objects.raw_query ({'name': {'$ regex': 'm'}})
panchicore

1
Если ваше значение RegEx происходит из пользовательского ввода (например, формы фильтра), и вы не хотите, чтобы само значение принималось как RegExp, вы можете применить к нему preg_quote ().
Филипп Рибер

2
Я только что понял это, но это на самом деле неправильный ответ, хотя он работает и является неоптимальным, вы должны вместо этого использовать фактический объект регулярного выражения BSON через MongoRegex, $ regex имеет проблемы совместимости с некоторыми командами, такими как $ in
Sammaye

Этот синтаксис полезен, если значение хранится в переменной, поэтому запрос можно записать в виде (в Ruby):$collection.where(field => {"$regex" => value})
Donny Kurnia

Но почему вы не можете использовать литералы массива?
Альпер

53

Вы бы использовали регулярные выражения для этого в Монго.

например: db.users.find({"name": /^m/})


29
Я думаю, что это показывает только документы со значением имени, которое начинается с "m"
JackAce

53

Там уже много ответов. Я даю различные типы требований и решений для поиска строк с помощью регулярных выражений.

Вы можете сделать с регулярным выражением, которые содержат слово, например, как. Также вы можете использовать $options => iдля поиска без учета регистра

Содержит string

db.collection.find({name:{'$regex' : 'string', '$options' : 'i'}})

Не содержит stringтолько регулярных выражений

db.collection.find({name:{'$regex' : '^((?!string).)*$', '$options' : 'i'}})

Точный регистр нечувствителен string

db.collection.find({name:{'$regex' : '^string$', '$options' : 'i'}})

Начать с string

db.collection.find({name:{'$regex' : '^string', '$options' : 'i'}})

Конец с string

db.collection.find({name:{'$regex' : 'string$', '$options' : 'i'}})

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


37

У вас есть 2 варианта:

db.users.find({"name": /string/})

или

db.users.find({"name": {"$regex": "string", "$options": "i"}})

На втором у вас есть больше опций, например «i» в опциях, чтобы найти использование без учета регистра. А что касается «строки», вы можете использовать, например, «. String. » (% String%) или «string. *» (String%) и «. * String) (% string). Вы можете использовать регулярное выражение как пожелаете.

Наслаждайтесь!


34

Если используется node.js , он говорит, что вы можете написать это:

db.collection.find( { field: /acme.*corp/i } );
//or
db.collection.find( { field: { $regex: 'acme.*corp', $options: 'i' } } );

Также вы можете написать это:

db.collection.find( { field: new RegExp('acme.*corp', 'i') } );

Аналогичный синтаксис в Ruby:collection.where(field => Regexp.new(value))
Донни Курния

24

Уже у вас есть ответы, но чтобы сопоставить регулярное выражение с учетом регистра

Вы можете использовать следующий запрос

db.users.find ({ "name" : /m/i } ).pretty()

iВ /m/iпоказывает случай нечувствительность и .pretty()обеспечивает более симпатичный выход


но что, если я хочу установить значение динамически здесь
KS

@KuldeepKoranga вы можете поместить любое динамическое значение вместо 'm'. Это то что ты хочешь.
The6thSense

var search="feacebook"так как я могу установить ниже @ The6thSens Да, но db.users.find ({ "name" : /search/i } )?
KS

@KuldeepKoranga вы назначаете значение.
The6thSense

1
@KuldeepKoranga stackoverflow.com/questions/7790811/… это помогает
The6thSense


13

Вы можете использовать новую функцию 2.6 mongodb:

db.foo.insert({desc: "This is a string with text"});
db.foo.insert({desc:"This is a another string with Text"});
db.foo.ensureIndex({"desc":"text"});
db.foo.find({
    $text:{
        $search:"text"
    }
});

6
Обратите внимание, что текстовый поиск AFAIK Mongodb работает на целых словах только по умолчанию, поэтому он будет соответствовать значениям типа «Это строка с текстом», но не «Это строка с подтекстом». Так что это не совсем похоже на оператор sql "LIKE".
rocketmonkeys

@Rocketmonkeys это правда .. для чего-то вроде «LIKE operator» вы бы использовали $ regex mongo operator.
cmarrero01

13

В проекте nodejs и использовании mongoose используйте запрос Like

var User = mongoose.model('User');

var searchQuery={};
searchQuery.email = req.query.email;
searchQuery.name = {$regex: req.query.name, $options: 'i'};
User.find(searchQuery, function(error, user) {
                if(error || user === null) {
                    return res.status(500).send(error);
                }
                return res.status(200).send(user);
            });

Как я могу использовать как запрос? Я пробовал это, но не работает:searchQuery.product_name = '/'+req.query.search.value+'/i';
Мухаммед Шахзад

можно попробовать как:searchQuery.product_name= {$regex: req.query.search.value, $options: 'i'};
Shaishab Roy

Ты спас мне жизнь, чувак. Можете ли вы объяснить, что такое $ regex и $ options?
Мухаммед Шахзад

if(req.query.search.value){ searchQuery.product_name = {$regex: req.query.search.value, $options: 'i'}; searchQuery.sale_amount = {$regex: req.query.search.value, $options: 'i'}; searchQuery.sale_person = {$regex: req.query.search.value, $options: 'i'}; searchQuery.department_name = {$regex: req.query.search.value, $options: 'i'}; searchQuery.sale_date = {$regex: req.query.search.value, $options: 'i'}; }Можете ли вы посмотреть, почему это не работает?
Мухаммед Шахзад

хорошо $regex: 'value' сгенерируйте регулярное выражение для вашего значения поиска и $options: 'i'означает, что регистр не учитывается . Ваш код не работал из - за вы использовали одинаковое значение для различных форм собственности и которые действуют как и условия , которые не должны выполнять с вашей коллекции баз данных.
Шайшаб Рой

12

Для PHP Монго Нравится.
У меня было несколько проблем с PHP как Монго. я обнаружил, что объединение параметров регулярных выражений помогает в некоторых ситуациях, когда поле поиска PHP mongo начинается с . Я решил опубликовать здесь, чтобы способствовать более популярной теме

например

db()->users->insert(['name' => 'john']);
db()->users->insert(['name' => 'joe']);
db()->users->insert(['name' => 'jason']);

// starts with
$like_var = 'jo';
$prefix = '/^';
$suffix = '/';
$name = $prefix . $like_var . $suffix;
db()->users->find(['name' => array('$regex'=>new MongoRegex($name))]);
output: (joe, john)

// contains
$like_var = 'j';
$prefix = '/';
$suffix = '/';
$name = $prefix . $like_var . $suffix;
db()->users->find(['name' => array('$regex'=>new MongoRegex($name))]);

output: (joe, john, jason)

Как и в предыдущих ответах и ​​комментариях, поиск в $ text (Index) даст лучшее решение с эталонным тестом по сравнению с правильным методом $ regex. Для справки проверьте эту ссылку stackoverflow.com/questions/10610131/… . Возможно ли реализовать метод $ text index с помощью PHP и mongoDB
sankar muniyappa

12

Использование литералов шаблона с переменными также работает:

{"firstname": {$regex : `^${req.body.firstname}.*` , $options: 'si' }}


Это поиск с начала ex - если "firstname" содержит testlast и если я ищу по "last", это не даст результата.
Викас Чаухан

11

С MongoDB Compass вам необходимо использовать синтаксис строгого режима, например:

{ "text": { "$regex": "^Foo.*", "$options": "i" } }

(В MongoDB Compass важно использовать "вместо ')


10

Вы можете использовать оператор where для построения любого JS-скрипта:

db.myCollection.find( { $where: "this.name.toLowerCase().indexOf('m') >= 0" } );

Ссылка: http://docs.mongodb.org/manual/reference/operator/where/


9
$whereочень неэффективно. Сделайте полное сканирование коллекции :(
Sushant Gupta

ах, нет проблем, я просто так сказал: D
Sushant Gupta

10

В SQL запрос « like » выглядит так:

select * from users where name like '%m%'

В консоли MongoDB это выглядит так:

db.users.find({"name": /m/})     // Not JSON formatted

db.users.find({"name": /m/}).pretty()  // JSON formatted

В дополнение pretty()метод будет во всех местах, где производят форматированную структуру JSON, которая является более читаемой.


10

Regex - это дорогой процесс.

Другой способ - создать индекс текста, а затем выполнить поиск по нему $search.

Создайте текстовый указатель полей, которые вы хотите сделать доступным для поиска:

db.collection.createIndex({name: 'text', otherField: 'text'});

Поиск строки в текстовом индексе:

db.collection.find({
  '$text'=>{'$search': "The string"}
})

Идеальное решение ... Regex - это дорогой способ. Работа с набором данных из 20 млн документов и разница в производительности очень очень заметна (что является преуменьшением)
nivensookharan

1
Действительно, это работает только для целых слов, см. Docs.mongodb.com/manual/core/index-text/#index-entries
Томас Эберт

8

В Go и MGO драйвер:

Collection.Find(bson.M{"name": bson.RegEx{"m", ""}}).All(&result)

где результат - экземпляр структуры искомого типа


2
Пожалуйста, избегайте необязательных полей в литералах, делайте bson:RegEx{Pattern:"m", Options:"i"}вместо этого
bithavoc

8

Используйте совпадения регулярных выражений, как показано ниже. «I» показывает нечувствительность к регистру.

var collections = mongoDatabase.GetCollection("Abcd");

var queryA = Query.And(
         Query.Matches("strName", new BsonRegularExpression("ABCD", "i")), 
         Query.Matches("strVal", new BsonRegularExpression("4121", "i")));

var queryB = Query.Or(
       Query.Matches("strName", new BsonRegularExpression("ABCD","i")),
       Query.Matches("strVal", new BsonRegularExpression("33156", "i")));

var getA = collections.Find(queryA);
var getB = collections.Find(queryB);

6

Как запрос будет как показано ниже

db.movies.find({title: /.*Twelve Monkeys.*/}).sort({regularizedCorRelation : 1}).limit(10);

для Scala ReactiveMongo API,

val query = BSONDocument("title" -> BSONRegex(".*"+name+".*", "")) //like
val sortQ = BSONDocument("regularizedCorRelation" -> BSONInteger(1))
val cursor = collection.find(query).sort(sortQ).options(QueryOpts().batchSize(10)).cursor[BSONDocument]

6

Кажется, что есть причины использовать как /regex_pattern/шаблон javascript , так и {'$regex': 'regex_pattern'}шаблон mongo . Смотрите: Ограничения синтаксиса MongoBD RegEx

Это не полный учебник по RegEx, но я был вдохновлен на выполнение этих тестов после того, как увидел неоднозначный пост с высоким рейтингом выше .

> ['abbbb','bbabb','bbbba'].forEach(function(v){db.test_collection.insert({val: v})})

> db.test_collection.find({val: /a/})
{ "val" : "abbbb" }
{ "val" : "bbabb" }
{ "val" : "bbbba" }

> db.test_collection.find({val: /.*a.*/})
{ "val" : "abbbb" }
{ "val" : "bbabb" }
{ "val" : "bbbba" }

> db.test_collection.find({val: /.+a.+/})
{ "val" : "bbabb" }

> db.test_collection.find({val: /^a/})
{ "val" : "abbbb" }

> db.test_collection.find({val: /a$/})
{ "val" : "bbbba" }

> db.test_collection.find({val: {'$regex': 'a$'}})
{ "val" : "bbbba" }

5

Если вы используете Spring-Data Mongodb, вы можете сделать это следующим образом:

String tagName = "m";
Query query = new Query();
query.limit(10);        
query.addCriteria(Criteria.where("tagName").regex(tagName));

4

Поскольку оболочка Mongo поддерживает регулярные выражения, это вполне возможно.

db.users.findOne({"name" : /.*sometext.*/});

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

db.users.findOne({"name" : /.*sometext.*/i});


4

Используйте поиск по подстроке агрегации (с индексом !!!):

db.collection.aggregate([{
        $project : {
            fieldExists : {
                $indexOfBytes : ['$field', 'string']
            }
        }
    }, {
        $match : {
            fieldExists : {
                $gt : -1
            }
        }
    }, {
        $limit : 5
    }
]);

отлично! Есть ли способ получить весь документ совпадает? или заставить каркас агрегации сделать дополнительный запрос, чтобы сделать это? На данный момент матч выглядит так:{ "_id" : ObjectId("5aba5ad988385120a01b1ac2"), "fieldExists" : 4 }
Джанфранко П.

в $ project stage просто проект, что вы хотите
Vokail

4

Струнный дипакпармар, дипак, пармар

db.getCollection('yourdb').find({"name":/^dee/})

и дипакпармар

db.getCollection('yourdb').find({"name":/d/})

и дипакпармар, дипак

db.getCollection('yourdb').find({"name":/mar$/})

анс дипакпармар, пармар


2

Я нашел бесплатный инструмент для перевода запросов MYSQL в MongoDB. http://www.querymongo.com/ Я проверил несколько запросов. как я вижу, почти все они верны. В соответствии с этим, ответ

db.users.find({
    "name": "%m%"
});

2

MongoRegex устарела.
Используйте MongoDB \ BSON \ Regex

$regex = new MongoDB\BSON\Regex ( '^m');
$cursor = $collection->find(array('users' => $regex));
//iterate through the cursor

Важно отметить, что это относится к классу MongoRegex в PHP . Не очень актуален этот вопрос, который касается Node. Вероятно, это должен быть комментарий или, что еще лучше - вопрос с самостоятельным ответом в отдельном посте.
Вооз - восстановить Монику

2
db.customer.find({"customerid": {"$regex": "CU_00000*", "$options": "i"}}).pretty()

Когда мы ищем строковые шаблоны, всегда лучше использовать вышеуказанный шаблон, когда мы не уверены в регистре. Надеюсь, это поможет!!!

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.