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

1438

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

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

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

Freewind
источник
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). Вы можете использовать регулярное выражение как пожелаете.

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

user3645907
источник
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()обеспечивает более симпатичный выход

The6thSense
источник
но что, если я хочу установить значение динамически здесь
KS
@KuldeepKoranga вы можете поместить любое динамическое значение вместо 'm'. Это то что ты хочешь.
The6thSense
var search="feacebook"так как я могу установить ниже @ The6thSens Да, но db.users.find ({ "name" : /search/i } )?
KS
@KuldeepKoranga вы назначаете значение.
The6thSense
1
@KuldeepKoranga stackoverflow.com/questions/7790811/… это помогает
The6thSense
18

Для мангуста в Node.js

db.users.find({'name': {'$regex': '.*sometext.*'}})
Акиб Мумтаз
источник
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"
    }
});
cmarrero01
источник
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' }}

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

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

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

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

DAMD
источник
10

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

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

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

briba
источник
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]
prayagupd
источник
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));
Vaibhav
источник
4

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

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

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

db.users.findOne({"name" : /.*sometext.*/i});
sravanthi
источник
4

Если вы хотите поиск «Мне нравится» в Монго, используйте $ regex, используя этот запрос:

db.product.find({name:{$regex:/m/i}})

для более подробной информации вы также можете прочитать документацию. https://docs.mongodb.com/manual/reference/operator/query/regex/

Джарри Яфери
источник
4

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

db.collection.aggregate([{
        $project : {
            fieldExists : {
                $indexOfBytes : ['$field', 'string']
            }
        }
    }, {
        $match : {
            fieldExists : {
                $gt : -1
            }
        }
    }, {
        $limit : 5
    }
]);
kz_sergey
источник
отлично! Есть ли способ получить весь документ совпадает? или заставить каркас агрегации сделать дополнительный запрос, чтобы сделать это? На данный момент матч выглядит так:{ "_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()

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

Прия Радж
источник