Jak wysłać zapytanie do MongoDB za pomocą „Lubię to”?


1437

Chcę zapytać o coś za pomocą likezapytania SQL :

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

Jak mogę osiągnąć to samo w MongoDB? Nie mogę znaleźć operatora likew dokumentacji .


7
zobacz dokumenty mongodb: Zaawansowane zapytania - Wyrażenia regularne mongodb.org/display/DOCS/…
— douyw

7
Twoje pytanie ma co najmniej 5głosy na tag operatora podobnego . Czy mogę prosić o zasugerowanie sql-like jako synonimu ?
— Kermit

3
Ten link może pomóc Ci goo.gl/gdTYK8
— Dilip Kr Singh

Odpowiedzi:


1945

To musiałoby być:

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

lub podobne:

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

Szukasz czegoś, co zawiera gdzieś „m” ( %operator SQL jest odpowiednikiem „Regexp .*”), a nie czegoś, co „m” jest zakotwiczone na początku łańcucha.

Uwaga: mongodb używa wyrażeń regularnych, które są silniejsze niż „LIKE” w sql. Za pomocą wyrażeń regularnych możesz stworzyć dowolny wzór, jaki sobie wyobrażasz.

Więcej informacji na temat wyrażeń regularnych można znaleźć pod tym linkiem https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions


96
czy wyszukiwanie według wyrażenia regularnego jest drogie?
— Freewind

147
Właściwie to zależy. Jeśli zapytanie nie korzysta z indeksu i musi wykonać skanowanie tabeli, z pewnością może być drogie. Jeśli wykonujesz zapytanie regularne „zaczyna się od”, wówczas można użyć indeksu. Najlepiej uruchomić wyjaśnienie (), aby zobaczyć, co się dzieje.
— Kyle Banker

35
Gdy nie jest zakotwiczony na początku sznurka, jest nieco drogi. Ale z drugiej strony, podobnie jak LIKEzapytanie w SQL.
— Emily,

4
więc dopóki jest zakotwiczony na początku łańcucha, jest w porządku? wiec super. oznacza to, że musimy dodać ^
— user4951

44
Dodałbym regex ijavascript db.users.find({ "name": { $regex: /m/i } })
— Doron Segal

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

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

obecnie: paulo, patric

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

obecnie: paulo, patric

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

obecnie: pedro


niezły przykład! Znajduję koniec czeku ze spacją i znalazłem to :) / $ /
— Phuong

jak znaleźć wszystkie wpisy dla imienia i nazwiska? lub symbol wieloznaczny dla * w SQL? Coś, select name from users;co robi, co tylko listy wszystkich użytkowników?
— anon58192932,

1
@ anon58192932 Aby wyświetlić wszystkie wpisy tylko pola „nazwa” w tabeli o nazwie „użytkownicy”, możesz użyć metody project (), ustawiając wartości pól, które chcesz 1. Pola, które nie są wymienione w projekcie (), nie będą pobrano oprócz _id. Pole _id jest drukowane domyślnie, co można pominąć, wprowadzając wartość 0 dla _id wewnątrz metody project (). Coś w stylu - db.collection.find (). Project ({name: 1, _id: 0}) .toArray (function (err, docs) {console.log (docs); callback (docs);}); Zapoznaj się z tym - docs.mongodb.com/manual/tutorial/…
— gauravparmar

282

W

  • PyMongo używa Pythona
  • Mongoose przy użyciu Node.js
  • Jongo , używając Java
  • mgo , używając Go

możesz to zrobić:

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

2
działa dobrze dla wyszukiwania z rozróżnianiem wielkości liter. Czy możesz mi powiedzieć, jak mogę sprawić, by wyszukiwanie bez rozróżniania wielkości liter było możliwe?
— Tahir Yasin

Jaki byłby regex%sometext%
— Tahir Yasin

64
@TahirYasin, jeśli nadal się zastanawiasz, wyszukiwanie bez rozróżniania wielkości liter byłoby takie:db.users.find({'name': {'$regex': 'sometext', '$options': 'i'}})
— sumowrestler

Rozwiązałem w golang używając mgo po prostu kod w ten sposób, selektor: = bson.M {"technician": bson.M {"$ regex": tech}}
— Sandun Priyanka

1
Uważaj, że to powinna być zaakceptowana odpowiedź. Obecnie jest najprostszy i najbardziej elegancki.
— Brett84c,

88

W PHP możesz użyć następującego kodu:

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

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

1
Jeśli twoja wartość RegEx pochodzi z danych wprowadzonych przez użytkownika (np. Formularz filtru) i nie chcesz, aby sama wartość była traktowana jako RegExp, możesz zastosować do niej funkcję preg_quote ().
— Philipp Rieber,

2
Właśnie zdałem sobie z tego sprawę, ale w rzeczywistości jest to zła odpowiedź, nawet jeśli działa, nie jest optymalna, powinieneś zamiast tego użyć rzeczywistego obiektu wyrażenia regularnego BSON przez MongoRegex, $ regex ma problemy z kompatybilnością z niektórymi poleceniami, takimi jak $ in
— Sammaye

Ta składnia jest przydatna, jeśli wartość jest przechowywana w zmiennej, więc zapytanie można zapisać jako (w Ruby):$collection.where(field => {"$regex" => value})
— Donny Kurnia

Ale dlaczego nie możesz używać literałów tablicowych?
— Alper

53

Używałbyś do tego wyrażeń regularnych w mongo.

na przykład: db.users.find({"name": /^m/})


29
Myślę, że pokazuje to tylko dokumenty o wartości nazwy rozpoczynającej się od „m”
— JackAce,

53

Istnieje już wiele odpowiedzi. Podaję różnego rodzaju wymagania i rozwiązania dotyczące wyszukiwania ciągów za pomocą wyrażenia regularnego.

Możesz zrobić z wyrażeniami regularnymi, które zawierają słowo tj. Podobne. Możesz także użyć $options => ido wyszukiwania bez rozróżniania wielkości liter

Zawiera string

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

Nie zawiera stringtylko wyrażenia regularnego

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

Dokładnie bez rozróżniania wielkości liter string

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

Zacząć od string

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

Kończyć z string

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

Zachowaj to jako zakładkę i odniesienie do wszelkich innych potrzebnych zmian.


37

Masz 2 możliwości:

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

lub

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

Na drugim masz więcej opcji, takich jak „i” w opcjach wyszukiwania bez rozróżniania wielkości liter. Jeśli chodzi o „ciąg znaków”, możesz użyć na przykład „. Ciąg. ” (% Ciąg%) lub „ciąg. *” (Ciąg%) i „. * Ciąg) (% ciąg). Możesz użyć wyrażenia regularnego jak chcesz.

Cieszyć się!


34

Jeśli używasz node.js , oznacza to , że możesz napisać to:

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

Również , można napisać tak:

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

Podobna składnia w języku Ruby:collection.where(field => Regexp.new(value))
— Donny Kurnia

24

Masz już odpowiedzi, ale aby dopasować wyrażenie regularne do nieuwzględniania wielkości liter

Możesz użyć następującego zapytania

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

Symbol iin /m/iwskazuje niewrażliwość na wielkość liter i .pretty()zapewnia ładniejszy wynik


ale co, jeśli chcę tu ustawić wartość dynamicznie
— KS

@KuldeepKoranga możesz umieścić dowolną wartość dynamiczną zamiast „m”. czy tego chcesz?
— The6thSense,

var search="feacebook"więc jak mogę ustawić poniżej @ The6thSens Tak, ale db.users.find ({ "name" : /search/i } )?
— KS

@KuldeepKoranga przypisałeś wartość.
— The6thSense,

1
@KuldeepKoranga stackoverflow.com/questions/7790811/... czy to pomaga
— The6thSense


13

Możesz użyć nowej funkcji 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
Uwaga: wyszukiwanie tekstowe AFAIK Mongodb domyślnie działa tylko na całych słowach, więc dopasuje wartości takie jak „To jest ciąg z tekstem”, ale nie „To jest ciąg z podtekstem”. Więc to nie jest całkiem jak operator „LIKE” w sql.
— rocketmonkeys,

@Rocketmonkeys to prawda .. dla czegoś takiego jak „operator LIKE” użyłbyś operatora $ regex mongo.
— cmarrero01,

13

W projekcie nodejs i użyj mangusty użyj zapytania 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);
            });

Jak korzystać z zapytania? Próbowałem tego, ale nie działa:searchQuery.product_name = '/'+req.query.search.value+'/i';
— Muhammad Shahzad

może spróbować:searchQuery.product_name= {$regex: req.query.search.value, $options: 'i'};
— Shaishab Roy

Uratuj mi życie koleś. czy możesz wyjaśnić trochę, czym jest $ regex i $ options?
— Muhammad Shahzad

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'}; }czy możesz sprawdzić, dlaczego to nie działa?
— Muhammad Shahzad

dobrze $regex: 'value' generuje wyrażenie regularne dla wartości wyszukiwania i $options: 'i'oznacza, że wielkość liter nie jest rozróżniana . Twój kod nie działa z powodu użyłeś samą wartość dla różnych własności i które działają jak i warunek, który należy spełnić nie ze swojej kolekcji bazy danych.
— Shaishab Roy,

12

Dla PHP mongo Like.
Miałem kilka problemów z php mongo jak. odkryłem, że konkatenacja parametrów wyrażenia regularnego pomaga w niektórych sytuacjach zaczyna się od pola znajdowania mongo PHP . Pomyślałem, że opublikuję tutaj, aby przyczynić się do bardziej popularnego wątku

na przykład

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)

Zgodnie z poprzednimi odpowiedziami i komentarzami wyszukiwanie $ text (Index) daje lepsze rozwiązanie z testem porównawczym w porównaniu z metodą $ regex. Dla porównania sprawdź ten link stackoverflow.com/questions/10610131/... . Czy możliwe jest zaimplementowanie metody $ text index z PHP i mongoDB
— sankar muniyappa

12

Działa także użycie literałów szablonów ze zmiennymi:

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


Jest to wyszukiwanie od początku ex - jeśli „imię” zawiera testlast, a jeśli szukam „last”, to nie da wyniku.
— Vikas Chauhan

11

W MongoDB Compass musisz użyć składni trybu ścisłego, takiej jak:

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

(W kompasie MongoDB ważne jest, aby używać "zamiast ')



10

W SQL zapytanie „ like ” wygląda następująco:

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

W konsoli MongoDB wygląda to tak:

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

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

Ponadto pretty()metoda będzie we wszystkich miejscach, w których sformatowana struktura JSON jest bardziej czytelna.


10

Regex są drogie to proces.

Innym sposobem jest utworzenie indeksu tekstu, a następnie wyszukiwanie go za pomocą $search.

Utwórz tekstowy Indeks pól, które chcesz umożliwić wyszukiwanie:

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

Wyszukaj ciąg w indeksie tekstowym:

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

Idealne rozwiązanie ... Regex to droga droga. Praca z zestawem danych obejmującym 20 mln dokumentów i różnicą wydajności jest bardzo bardzo zauważalna (co jest mało powiedziane)
— nivensookharan

1
Rzeczywiście, działa to tylko dla całych słów, patrz docs.mongodb.com/manual/core/index-text/#index-entries
— Thomas Ebert

8

W Go i sterowniku mgo:

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

gdzie wynik jest instancją struct poszukiwanego typu


2
proszę, unikajcie nieprzypisanych pól w literałach, bson:RegEx{Pattern:"m", Options:"i"}zamiast tego
— bithavoc,

8

Użyj wyrażeń regularnych pasujących jak poniżej. „I” pokazuje niewrażliwość na wielkość liter.

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

Podobnie jak w przypadku zapytania, jak pokazano poniżej

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

dla interfejsu API Scala ReactiveMongo ,

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

Wydaje się, że istnieją powody stosowania zarówno /regex_pattern/wzorca javascript , jak i {'$regex': 'regex_pattern'}wzoru mongo . Zobacz: Ograniczenia składni Reggo MongoBD

To nie jest kompletny samouczek RegEx, ale zainspirowałem się do uruchomienia tych testów po zobaczeniu wysoko głosowanego dwuznacznego postu powyżej .

> ['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

Jeśli korzystasz z Mongodb Spring-Data, możesz to zrobić w następujący sposób:

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

4

Ponieważ regex obsługuje powłokę Mongo, jest to całkowicie możliwe.

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

Jeśli chcemy, aby zapytanie nie rozróżniało wielkości liter, możemy użyć opcji „i”, jak pokazano poniżej:

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


4

Użyj wyszukiwania podciągów agregacji (z indeksem !!!):

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

miły! czy istnieje sposób na dopasowanie całego dokumentu? lub zmusić strukturę agregującą do wykonania zapytania uzupełniającego, aby to zrobić? W tej chwili mecz wygląda następująco:{ "_id" : ObjectId("5aba5ad988385120a01b1ac2"), "fieldExists" : 4 }
— Gianfranco P.

w fazie projektu $ po prostu projektuj, co chcesz
— Vokail

4

Sznurek 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

Znalazłem bezpłatne narzędzie do tłumaczenia zapytań MYSQL na MongoDB. http://www.querymongo.com/ Sprawdziłem kilka zapytań. jak widzę, prawie wszystkie z nich są poprawne. Zgodnie z tym, odpowiedź brzmi

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

2

MongoRegex został uznany za przestarzały.
Użyj MongoDB \ BSON \ Regex

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

Należy zauważyć, że odnosi się to do klasy MongoRegex w PHP . Niezbyt istotne w przypadku tego pytania dotyczącego węzła. To prawdopodobnie powinien być komentarz lub jeszcze lepiej - pytanie, na które odpowiedziano samodzielnie w oddzielnym poście.
— Boaz - Przywróć Monikę

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

Kiedy szukamy wzorców ciągów, zawsze lepiej jest użyć powyższego wzorca, ponieważ nie jesteśmy pewni wielkości liter. Mam nadzieję, że to pomaga !!!

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.