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.