Bagaimana cara menanyakan MongoDB dengan "suka"?

1437

Saya ingin menanyakan sesuatu dengan likepermintaan SQL :

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

Bagaimana cara saya mencapai hal yang sama di MongoDB? Saya tidak dapat menemukan operator likedalam dokumentasi .

Freewind
sumber
7
lihat dokumen mongodb: Kueri Tingkat Lanjut - Ekspresi reguler mongodb.org/display/DOCS/…
douyw
7
Pertanyaan Anda setidaknya memiliki 5suara untuk tag seperti operator . Bisakah saya meminta agar Anda menyarankan seperti sql sebagai sinonim ?
Kermit
3
Tautan ini dapat membantu Anda goo.gl/gdTYK8
Dilip Kr Singh

Jawaban:

1945

Itu pasti:

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

atau, serupa:

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

Anda sedang mencari sesuatu yang mengandung "m" di suatu tempat ( %operator SQL ' setara dengan Regexp' .*'), bukan sesuatu yang memiliki "m" berlabuh ke awal string.

catatan: mongodb menggunakan ekspresi reguler yang lebih kuat daripada "LIKE" dalam sql. Dengan ekspresi reguler, Anda dapat membuat pola apa pun yang Anda bayangkan.

Untuk info lebih lanjut tentang ekspresi reguler, lihat tautan ini https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions

Kyle H
sumber
96
Apakah pencarian dengan regex mahal?
Freewind
147
Sebenarnya itu tergantung. Jika kueri tidak menggunakan indeks, dan harus melakukan pemindaian tabel, maka pastinya bisa mahal. Jika Anda melakukan permintaan regex 'dimulai dengan', maka itu bisa menggunakan indeks. Terbaik untuk menjalankan penjelasan () untuk melihat apa yang terjadi.
Kyle Banker
35
Ketika tidak berlabuh ke awal string, itu agak mahal. Tapi sekali lagi, begitu pula LIKEpermintaan dalam SQL.
Emily
4
jadi selama itu berlabuh ke awal string tidak apa-apa? keren kalau begitu. apakah itu berarti kita perlu menambahkan ^
user4951
44
Saya akan menambahkan 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%'

keluar: paulo, patric

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

keluar: paulo, patric

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

keluar: pedro

Johnathan Douglas
sumber
contoh yang bagus! Saya menemukan ujung cek dengan ruang dan menemukan ini :) / $ /
Phuong
bagaimana Anda menemukan semua entri untuk nama? atau wildcard untuk * dalam SQL? Sesuatu yang tidak select name from users;hanya mencantumkan semua pengguna?
anon58192932
1
@ anon58192932 Untuk menampilkan semua entri hanya bidang "nama" dalam tabel bernama "pengguna", Anda dapat menggunakan metode project () dengan menetapkan nilai bidang yang ingin Anda 1. Bidang yang tidak disebutkan dalam proyek () tidak akan diambil kecuali _id. Bidang _id dicetak secara default yang dapat Anda tekan dengan meletakkan nilai 0 untuk metode _id di dalam project (). Sesuatu seperti - db.collection.find (). Project ({name: 1, _id: 0}) .toArray (fungsi (err, docs) {console.log (docs); callback (docs);}); Merujuk ini - docs.mongodb.com/manual/tutorial/...
gauravparmar
282

Di

  • PyMongo menggunakan Python
  • Mongoose menggunakan Node.js
  • Jongo , menggunakan Java
  • mgo , menggunakan Go

Anda dapat melakukan:

db.users.find({'name': {'$regex': 'sometext'}})
Afshin Mehrabani
sumber
2
berfungsi baik untuk pencarian case sensitif, bisakah Anda memberi tahu saya bagaimana saya bisa membuatnya bekerja untuk melakukan pencarian case sensitif?
Tahir Yasin
Apa yang akan menjadi regex untuk%sometext%
Tahir Yasin
64
@TahirYasin jika Anda masih bertanya-tanya, pencarian case-insensitive akan dilakukan seperti ini:db.users.find({'name': {'$regex': 'sometext', '$options': 'i'}})
sumowrestler
Saya menyelesaikannya di golang menggunakan kode sederhana mgo seperti ini, pemilih: = bson.M {"teknisi": bson.M {"$ regex": tech}}
Sandun Priyanka
1
Merasa seperti ini harus menjadi jawaban yang diterima. Ini yang paling sederhana dan paling elegan saat ini.
Brett84c
88

Di PHP, Anda dapat menggunakan kode berikut:

$collection->find(array('name'=> array('$regex' => 'm'));
leon
sumber
4
python + mongoengine: people = People.objects.raw_query ({'name': {'$ regex': 'm'}})
panchicore
1
Jika nilai RegEx Anda berasal dari input pengguna (mis. Formulir filter) dan Anda tidak ingin nilai itu sendiri diambil sebagai RegExp, Anda harus menerapkan preg_quote () untuknya.
Philipp Rieber
2
Saya baru menyadari ini, tetapi ini sebenarnya jawaban yang salah, meskipun itu berfungsi kurang optimal, Anda sebaiknya menggunakan objek regon BSON aktual melalui MongoRegex, $ regex memiliki masalah kompatibilitas dengan perintah tertentu seperti $ in
Sammaye
Sintaks ini berguna jika nilainya disimpan dalam variabel, sehingga kueri dapat ditulis sebagai (dalam Ruby):$collection.where(field => {"$regex" => value})
Donny Kurnia
Tetapi mengapa Anda tidak bisa menggunakan literal array?
Alper
53

Anda akan menggunakan regex untuk itu di mongo.

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

Joshua Partogi
sumber
29
Saya pikir ini hanya menunjukkan dokumen dengan nilai nama yang dimulai dengan "m"
JackAce
53

Sudah ada banyak jawaban. Saya memberikan berbagai jenis persyaratan dan solusi untuk pencarian string dengan regex.

Anda dapat melakukannya dengan regex yang berisi kata seperti like. Anda juga dapat menggunakan $options => iuntuk pencarian case-sensitive

Mengandung string

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

Tidak Berisi stringhanya dengan regex

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

Tidak sensitif case persis string

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

Dimulai dari string

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

Berakhir dengan string

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

Simpan ini sebagai bookmark, dan referensi untuk perubahan lain yang mungkin Anda butuhkan.

Somnath Muluk
sumber
37

Anda memiliki 2 pilihan:

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

atau

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

Yang kedua Anda memiliki lebih banyak opsi, seperti "i" dalam opsi untuk menemukan penggunaan case-insensitive. Dan tentang "string", Anda dapat menggunakan seperti ". String. " (% String%), atau "string. *" (String%) dan ". * String) (% string) misalnya. Anda dapat menggunakan ekspresi reguler seperti yang kamu inginkan.

Nikmati!

pengguna3645907
sumber
34

Jika menggunakan node.js , itu mengatakan bahwa Anda dapat menulis ini:

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

Juga , Anda dapat menulis ini:

db.collection.find( { field: new RegExp('acme.*corp', 'i') } );
Eddy
sumber
Sintaks serupa di Ruby:collection.where(field => Regexp.new(value))
Donny Kurnia
24

Sudah Anda mendapatkan jawaban tetapi untuk mencocokkan regex dengan ketidakpekaan huruf

Anda bisa menggunakan kueri berikut

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

The idalam /m/imenunjukkan kasus ketidakpekaan dan .pretty()memberikan output lebih cantik

The6thSense
sumber
tetapi bagaimana jika saya ingin menetapkan nilai secara dinamis di sini
KS
@KuldeepKoranga Anda dapat menempatkan nilai dinamis apa pun di tempat 'm'. itu yang kamu inginkan.
The6thSense
var search="feacebook"jadi bagaimana saya bisa mengatur di bawah @ The6thSens Ya, tapi db.users.find ({ "name" : /search/i } )?
KS
@KuldeepKoranga Anda telah menetapkan nilainya.
The6thSense
1
@KuldeepKoranga stackoverflow.com/questions/7790811/… melakukan ini membantu
The6thSense
18

Untuk luwak di Node.js

db.users.find({'name': {'$regex': '.*sometext.*'}})
Aqib Mumtaz
sumber
13

Anda dapat menggunakan fitur baru 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
sumber
6
Catatan, pencarian teks AFAIK Mongodb hanya berfungsi pada seluruh kata secara default, jadi ini akan cocok dengan nilai-nilai seperti "Ini adalah string dengan teks", tetapi tidak "Ini adalah string dengan subteks". Jadi tidak seperti operator "LIKE" sql.
rocketmonkeys
@Rocketmonkeys itu benar .. untuk sesuatu seperti "LIKE operator", Anda akan menggunakan $ regex mongo operator.
cmarrero01
13

Dalam proyek nodejs dan gunakan luong gunakan Seperti permintaan

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
sumber
Bagaimana saya bisa menggunakan permintaan seperti? Saya telah mencoba ini tetapi tidak berhasil:searchQuery.product_name = '/'+req.query.search.value+'/i';
Muhammad Shahzad
dapat mencoba seperti:searchQuery.product_name= {$regex: req.query.search.value, $options: 'i'};
Shaishab Roy
Anda menyelamatkan hidup saya Bung. dapatkah Anda menjelaskan sedikit apa itu $ regex dan $ 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'}; }dapatkah Anda melihat mengapa ini tidak berhasil?
Muhammad Shahzad
juga $regex: 'value' menghasilkan ekspresi reguler untuk nilai pencarian dan Anda $options: 'i'berarti kasus sensitif . Kode Anda tidak berfungsi karena Anda menggunakan nilai yang sama untuk properti yang berbeda dan itu bertindak sebagai dan kondisi yang tidak boleh dipenuhi dengan koleksi database Anda.
Shaishab Roy
12

Untuk PHP mongo Like.
Saya punya beberapa masalah dengan php seperti mongo. Saya menemukan bahwa menggabungkan params regex membantu dalam beberapa situasi PHP mongo menemukan bidang dimulai dengan . Saya pikir saya akan memposting di sini untuk berkontribusi pada utas yang lebih populer

misalnya

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
sumber
Sesuai jawaban dan komentar sebelumnya, pencarian $ text (Index) akan memberikan solusi yang lebih baik dengan tolok ukur membandingkan dengan metode $ regex benar. Untuk referensi, periksa tautan ini stackoverflow.com/questions/10610131/… . Apakah mungkin untuk menerapkan metode $ text index dengan PHP dan
mongoDB
12

Menggunakan templat literal dengan variabel juga berfungsi:

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

besthost
sumber
Ini adalah searchig dari mulai ex - jika "firstname" mengandung testlast dan jika saya mencari dengan "last" tidak akan memberikan hasil.
Vikas Chauhan
11

Dengan Kompas MongoDB, Anda perlu menggunakan sintaks mode ketat, seperti:

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

(Dalam Kompas MongoDB, penting bahwa Anda menggunakan "bukan ')

sial
sumber
10

Anda dapat menggunakan pernyataan di mana untuk membuat skrip JS:

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

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

briba
sumber
9
$wheresangat tidak efisien. Lakukan pemindaian koleksi penuh :(
Sushant Gupta
ah, tidak masalah, saya hanya mengatakan itu: D
Sushant Gupta
10

Dalam SQL, kueri ' seperti ' terlihat seperti ini:

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

Di konsol MongoDB, tampilannya seperti ini:

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

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

Selain itu pretty()metode akan di semua tempat di mana menghasilkan struktur JSON diformat yang lebih mudah dibaca.

MADHAIYAN M
sumber
10

Regex adalah proses yang mahal.

Cara lain adalah dengan membuat indeks teks dan kemudian mencarinya menggunakan $search.

Buat Indeks teks bidang yang ingin Anda cari:

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

Cari string dalam indeks teks:

db.collection.find({
  '$text'=>{'$search': "The string"}
})
Karat
sumber
Solusi sempurna ... Regex adalah cara yang mahal. Bekerja dengan kumpulan data dokumen 20m dan perbedaan kinerja sangat sangat nyata (yang meremehkan)
nivensookharan
1
Memang, ini hanya berfungsi untuk seluruh kata, lihat docs.mongodb.com/manual/core/index-text/#index-entries
Thomas Ebert
8

In Go dan driver mgo:

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

di mana hasilnya adalah contoh struct dari tipe yang dicari


sumber
2
tolong hindari bidang yang tidak bson:RegEx{Pattern:"m", Options:"i"}
dikunci
8

Gunakan persamaan reguler yang cocok seperti di bawah ini. Huruf 'i' menunjukkan ketidakpekaan huruf besar-kecil.

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
sumber
6

Seperti Query akan seperti yang ditunjukkan di bawah ini

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

untuk 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]
prayagupd
sumber
6

Tampaknya ada alasan untuk menggunakan /regex_pattern/pola javascript maupun {'$regex': 'regex_pattern'}pola mongo . Lihat: Pembatasan Syntax MongoBD RegEx

Ini bukan tutorial RegEx yang lengkap, tetapi saya terinspirasi untuk menjalankan tes ini setelah melihat posting ambigu yang sangat terpilih di atas .

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

Jika Anda menggunakan Spring-Data Mongodb Anda bisa melakukan ini dengan cara ini:

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

Sebagai Mongo shell mendukung regex, itu sangat mungkin.

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

Jika kami ingin kueri tidak peka huruf besar-kecil, kami dapat menggunakan opsi "i", seperti yang ditunjukkan di bawah ini:

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

Gunakan pencarian substring agregasi (dengan indeks !!!):

db.collection.aggregate([{
        $project : {
            fieldExists : {
                $indexOfBytes : ['$field', 'string']
            }
        }
    }, {
        $match : {
            fieldExists : {
                $gt : -1
            }
        }
    }, {
        $limit : 5
    }
]);
kz_sergey
sumber
bagus! apakah ada cara agar seluruh dokumen cocok? atau membuat kerangka agregasi membuat kueri tindak lanjut untuk melakukan itu? Saat ini sebuah pertandingan terlihat seperti:{ "_id" : ObjectId("5aba5ad988385120a01b1ac2"), "fieldExists" : 4 }
Gianfranco P.
dalam $ tahap proyek hanya proyek apa yang Anda inginkan
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

Deepak parmar
sumber
2

Saya menemukan alat gratis untuk menerjemahkan pertanyaan MYSQL ke MongoDB. http://www.querymongo.com/ Saya memeriksa beberapa pertanyaan. seperti yang saya lihat hampir semuanya benar. Menurut itu, jawabannya adalah

db.users.find({
    "name": "%m%"
});
Lakmal Vithanage
sumber
2

MongoRegex telah ditinggalkan.
Gunakan MongoDB \ BSON \ Regex

$regex = new MongoDB\BSON\Regex ( '^m');
$cursor = $collection->find(array('users' => $regex));
//iterate through the cursor
Albert s
sumber
Penting untuk dicatat bahwa ini merujuk ke kelas MongoRegex di PHP . Tidak terlalu relevan dengan pertanyaan ini yaitu tentang Node. Ini mungkin harus komentar atau lebih baik lagi - pertanyaan yang dijawab sendiri di pos terpisah.
Boaz - Reinstate Monica
2
db.customer.find({"customerid": {"$regex": "CU_00000*", "$options": "i"}}).pretty()

Saat kami mencari pola string, selalu lebih baik menggunakan pola di atas karena ketika kami tidak yakin dengan huruf besar-kecil. Semoga itu bisa membantu !!!

priya raj
sumber