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 .

Freewind
źródło
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

Kyle H.
źródło
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

Johnathan Douglas
źródło
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'}})
Afshin Mehrabani
źródło
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'));
Leon
źródło
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/})

Joshua Partogi
źródło
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.

Somnath Muluk
źródło
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ę!

użytkownik3645907
źródło
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') } );
Wir
źródło
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

The6thSense
źródło
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
18

Dla Mongoose w Node.js

db.users.find({'name': {'$regex': '.*sometext.*'}})
Aqib Mumtaz
źródło
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"
    }
});
cmarrero01
źródło
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);
            });
Shaishab Roy
źródło
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)
Dap
źródło
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' }}

besthost
źródło
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 ')

cholera
źródło
10

Możesz użyć instrukcji where do zbudowania dowolnego skryptu JS:

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

Odniesienie: http://docs.mongodb.org/manual/reference/operator/where/

Briba
źródło
9
$wherejest wysoce nieefektywny. Wykonaj pełny skan kolekcji :(
Sushant Gupta,
ah, nie ma problemu, mówiłem właśnie tak: D
Sushant Gupta
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.

MADHAIYAN M.
źródło
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"}
})
Rdza
źródło
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


źródło
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);
Shalabh Raizada
źródło
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]
prayagupd
źródło
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" }
Bruno Bronosky
źródło
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));
Vaibhav
źródło
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});
śravanthi
źródło
4

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

db.collection.aggregate([{
        $project : {
            fieldExists : {
                $indexOfBytes : ['$field', 'string']
            }
        }
    }, {
        $match : {
            fieldExists : {
                $gt : -1
            }
        }
    }, {
        $limit : 5
    }
]);
kz_sergey
źródło
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

Deepak Parmar
źródło
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%"
});
Lakmal Vithanage
źródło
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
Albert s
źródło
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 !!!

priya raj
źródło