Як запитувати MongoDB за допомогою "like"?


1437

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

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

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


7
дивіться документи dongodb
douyw

7
У вашому запитанні є щонайменше 5голосів за тег " оператор" . Чи можу я просити Вас , що ви пропонуєте SQL-подібний як синонім ?
Керміт

3
Це посилання може допомогти вам goo.gl/gdTYK8
Діліп Кр Сінгх

Відповіді:


1945

Це повинно бути:

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

або, подібне:

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

Ви шукаєте щось, що містить "m" десь (оператор SQL " %" еквівалентний Regexp '.* "), а не те, що "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
Я додав би регекс ijavascript 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. Поля, які не згадуються в проекті (), не будуть отримано, крім _id. Поле _id друкується за замовчуванням, яке ви можете придушити, додавши значення 0 для методу _id всередині методу project (). Щось на зразок - db.collection.find (). Проект ({ім'я: 1, _id: 0}) .toArray (функція (помилка, документи) {console.log (docs); зворотний виклик (docs);}); Посилайтеся на це - docs.mongodb.com/manual/tutorial/…
gauravparmar

282

В

  • PyMongo за допомогою Python
  • Мангуст за допомогою Node.js
  • Jongo , використовуючи Java
  • mgo , використовуючи Go

Ви можете зробити:

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

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

Який би був регулярний вираз%sometext%
Тахір Ясін

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

Я вирішив в Голангу, використовуючи mgo, просто такий код, селектор: = bson.M {"технік": bson.M {"$ regex": tech}}
Садун Приянка

1
Відчуваю, що це має бути прийнятою відповіддю. Це найпростіший і найелегантніший на даний момент.
Brett84c

88

У PHP ви можете використовувати наступний код:

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

4
python + mongoengine: people = People.objects.raw_query ({'ім'я': {'$ 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

Відповідей уже багато. Я висуваю різні типи вимог та рішень для пошуку рядків за допомогою regex.

Ви можете зробити з регулярними виразами, які містять слово, наприклад, подібне. Також ви можете використовувати $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

У вас є два варіанти:

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))
Donny Kurnia

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 } )?
КС

@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 працює на цілі слова лише за замовчуванням, тому це буде відповідати значенням типу "Це рядок з текстом", але не "Це рядок з підтекстом". Тож це не зовсім схоже на оператора "LIKE" sql.
rocketmonkeys

@Rocketmonkeys є її правдою .. для чогось типу "LIKE operator" ви б використовували оператор $ regex mongo.
cmarrero01

13

У проекті nodejs і використовуйте мангустне використання Like query

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'};
Шайшаб Рой

Ти врятуєш мого чувака життя. Ви можете трохи пояснити, що таке $ 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 mongo Like.
У мене було кілька проблем з php mongo, як. Я виявив, що об'єднання параграм регулярного виразів допомагає в деяких ситуаціях 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' }}


Це searchig починаючи з колишнього - якщо "ім'я" містить testlast, а якщо я шукаю за "останнім", це не дасть результат.
Вікас Чаухан

11

Для MongoDB Compass вам потрібно використовувати синтаксис суворого режиму як такий:

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

(У MongoDB Compass важливо використовувати його "замість ')


10

Ви можете використовувати де оператор для створення будь-якого сценарію 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 запит " як " виглядає так:

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-мільйонних документах та різниця в продуктивності дуже помітна (що
занижує значення

1
Дійсно, це працює лише для цілих слів, див. Docs.mongodb.com/manual/core/index-text/#index-entries
Томас Еберт

8

У Go та mgo driver:

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

де результат - структурний екземпляр шуканого типу


2
pls уникайте непотрібних полів у літералах, зробіть bson:RegEx{Pattern:"m", Options:"i"}замість цього
bithavoc

8

Використовуйте відповідні регулярні вирази, як показано нижче. "Я" показує нечутливість до випадку.

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'}. Див.: Обмеження синтаксису RegEx MongoBD

Це не повний підручник з 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 }
Джанфранко П.

на етапі $ проекту просто спроектуй те, що ти хочеш
Vokail

4

String deepakparmar, dipak, parmar

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

ans deepakparmar

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

ans deepakparmar, dipak

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

ans deepakparmar, parmar


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 . Не дуже актуально для цього питання, що стосується Вузла. Це, мабуть, має бути коментар, а ще краще - питання, яке я відповідав на себе в окремому дописі.
Боаз - Відновіть Моніку

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

Коли ми шукаємо рядкові шаблони, завжди краще використовувати вищевказаний зразок, як коли ми не впевнені у випадку. Сподіваюся, що допомагає !!!

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.