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

1012

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

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

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

  • 7
    см. документы mongodb: расширенные запросы - регулярные выражения mongodb.org/display/DOCS/…
  • 6
    Ваш вопрос набрал не менее 5 голосов за тег Like-оператора . Могу ли я попросить вас предложить sql-like в качестве синонима ?
Показать ещё 1 комментарий
Теги:
mongodb-query
sql-like

34 ответа

1365
Лучший ответ

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

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

или, аналогично:

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

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

  • 76
    дорогой поиск по регулярному выражению?
  • 2
    @Freewind: нет, это не дорого.
Показать ещё 13 комментариев
252
db.users.insert({name: 'paulo'})
db.users.insert({name: 'patric'})
db.users.insert({name: 'pedro'})

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

out: paulo, patric

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

out: paulo, patric

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

out: pedro

  • 0
    хороший пример! Я считаю, что проверка заканчивается пробелом и нашел это :) / $ /
  • 0
    как вы находите все записи по имени? или подстановочный знак для * в SQL? Что-то, что select name from users; который просто перечисляет всех пользователей?
Показать ещё 1 комментарий
199

В

  • PyMongo с помощью Python
  • Mongoose, используя Node.js
  • Jongo, используя Java
  • mgo, используя Go

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

db.users.find({'name': {'$regex': 'sometext'}})
  • 2
    он работает нормально для поиска с учетом регистра, подскажите, пожалуйста, как я могу заставить его выполнять поиск без учета регистра?
  • 0
    Что будет регулярным выражением для %sometext%
Показать ещё 5 комментариев
71

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

$collection->find(array('name'=> array('$regex' => 'm'));
  • 4
    python + mongoengine: people = People.objects.raw_query ({'name': {'$ regex': 'm'}})
  • 1
    Если ваше значение RegEx происходит из пользовательского ввода (например, формы фильтра), и вы не хотите, чтобы само значение принималось как RegExp, вы можете применить к нему preg_quote ().
Показать ещё 4 комментария
44

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

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

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

Если вы используете 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') } );
  • 0
    Аналогичный синтаксис в Ruby: collection.where(field => Regexp.new(value))
21

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

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

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

14

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

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

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

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

13

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

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

или

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

Во втором случае у вас есть больше опций, например, "i" в параметрах, которые можно найти с помощью нечувствительности к регистру. И о "строке", вы можете использовать как ".string". (% string%) или строка "." (строка%) и строка ". *) (например, строка%). Вы можете использовать регулярное выражение, как хотите.

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

11

Для Mongoose в Node.js

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

Вы можете использовать новую функцию 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".
  • 0
    @Rocketmonkeys это правда .. для чего-то вроде «LIKE operator» вы бы использовали $ regex mongo operator.
9

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

например

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)
  • 0
    Как и в предыдущих ответах и комментариях, поиск $ text (Index) даст лучшее решение с эталонным тестом по сравнению с правильным методом $ regex. Для справки проверьте эту ссылку stackoverflow.com/questions/10610131/… . Можно ли реализовать метод $ text index с помощью PHP и mongoDB
8

В проекте nodejs и используйте использование мангуста. Как запрос

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);
            });
  • 0
    Как я могу использовать как запрос? Я пробовал это, но не работает: searchQuery.product_name = '/'+req.query.search.value+'/i';
  • 0
    можно попробовать как: searchQuery.product_name= {$regex: req.query.search.value, $options: 'i'};
Показать ещё 5 комментариев
6

Используйте регулярные выражения, как показано ниже. "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

В 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

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

6

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

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

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

  • 9
    $where крайне неэффективно. Сделайте полную проверку коллекции :(
  • 0
    Признаюсь, я еще не тестировал производительность
Показать ещё 1 комментарий
5

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

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

где result является экземпляром struct искомого типа

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

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

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

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

4

Подобно запросу, как показано ниже

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]
3

Похоже, что есть причины использовать как шаблон javascript /regex_pattern/, так и шаблон mongo {'$regex': 'regex_pattern'}. Смотрите: Ограничения синтаксиса Reggo 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" }
3

Если вы хотите "Like" искать в mongo, тогда вы должны пойти с $regex, используя этот запрос будет

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

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

3

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

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

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

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

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

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

Regex - дорогостоящий процесс.

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

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

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

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

db.collection.find({
  '$text'=>{'$search': "The string"}
})
  • 0
    Идеальное решение ... Regex - это дорогой способ. Работа с набором данных из 20 млн документов и разница в производительности очень и очень заметна (что является преуменьшением)
  • 0
    Кажется, это работает только для целых слов.
Показать ещё 1 комментарий
2

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

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

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

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

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

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

db.collection.aggregate([{
        $project : {
            fieldExists : {
                $indexOfBytes : ['$field', 'string']
            }
        }
    }, {
        $match : {
            fieldExists : {
                $gt : -1
            }
        }
    }, {
        $limit : 5
    }
]);
  • 0
    отлично! Есть ли способ получить весь документ совпадает? или заставить каркас агрегации сделать дополнительный запрос, чтобы сделать это? На данный момент совпадение выглядит следующим образом: { "_id" : ObjectId("5aba5ad988385120a01b1ac2"), "fieldExists" : 4 }
  • 0
    в стадии $ проекта просто проект, что вы хотите
1
db.customer.find({"customerid": {"$regex": "CU_00000*", "$options": "i"}}).pretty()

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

1

FullName как "последний" со статусом == Ожидается между двумя датами:

db.orders.find({
      createdAt:{$gt:ISODate("2017-04-25T10:08:16.111Z"),
      $lt:ISODate("2017-05-05T10:08:16.111Z")},
      status:"Pending",
      fullName:/last/}).pretty();

status == 'Ожидание' и orderId LIKE 'PHA876174:

db.orders.find({
     status:"Pending",
     orderId:/PHA876174/
     }).pretty();
1

Если вы используете PHP, вы можете использовать MongoDB_DataObject оболочку, как показано ниже:

$model = new MongoDB_DataObject();

$model->query("select * from users where name like '%m%'");

while($model->fetch()) {
    var_dump($model);
}

ИЛИ

$model = new MongoDB_DataObject('users);

$model->whereAdd("name like '%m%'");

$model->find();

while($model->fetch()) {
    var_dump($model);
}
1

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

$regex = new MongoDB\BSON\Regex ( '^m');
$cursor = $collection->find(array('users' => $regex));
//iterate through the cursor
  • 0
    Важно отметить, что это относится к классу MongoRegex в PHP . Не очень актуален этот вопрос, который касается Node. Вероятно, это должен быть комментарий или, что еще лучше - вопрос с самостоятельным ответом в отдельном посте.
0

Вы также можете использовать фильтр подстановочных знаков следующим образом:

{"query": { "wildcard": {"lookup_field":"search_string*"}}}

обязательно используйте *.

0

db.car.distinct('name') [ "honda", "tat", "tata", "tata3" ]

db.car.find({ "name":/. ta./})

  • 0
    Вау, это, наверное, удивительный ответ. Хотите уточнить это?
0

использовать $regex в mongodb

как использовать регулярное выражение

Пример

select * from table where abc like %v%

in mongo

 var colName="v";
 models.customer.find({ "abc": { $regex: '.*' + colName + '.*' } },
   function(err,data){
         console.log('data',data);
  });

Ваш запрос выглядит как

var name="john";
UserSchema.find({name: { $regex: '.*' + name + '.*' } }).limit(5);

Ещё вопросы

Сообщество Overcoder
Наверх
Меню