Catatan untuk semua orang yang akan mencoba menggunakan jawaban yang melibatkan ekspresi reguler: Ekspresi reguler perlu disterilkan.
sean
Jawaban:
126
Solusi Chris Fulstow akan berfungsi (+1), namun, mungkin tidak efisien, terutama jika koleksi Anda sangat besar. Ekspresi reguler yang tidak di-root (yang tidak diawali dengan ^, yang menambatkan ekspresi reguler ke awal string), dan ekspresi reguler yang menggunakan itanda untuk ketidaksensitifan huruf besar / kecil tidak akan menggunakan indeks, meskipun ada.
Opsi alternatif yang dapat Anda pertimbangkan adalah mendenormalisasi data Anda untuk menyimpan namebidang versi huruf kecil , misalnya sebagai name_lower. Anda kemudian dapat membuat kueri yang efisien (terutama jika diindeks) untuk pencocokan tepat tidak peka huruf besar / kecil seperti:
Jawaban yang bagus, pendekatan regex saya benar-benar melambat setelah harus memindai beberapa juta dokumen.
Chris Fulstow
34
Ini sebenarnya tidak sepenuhnya benar, karena Anda mungkin menemukan "Andrew sesuatu" saat mencari "Andrew". Jadi sesuaikan regex menjadi: new RegExp('^'+ username + '$', "i")agar sama persis.
Tarion
9
Menurut situs web MongoDB, regex yang tidak peka huruf besar / kecil tidak efisien dalam indeks "$ regex hanya dapat menggunakan indeks secara efisien ketika persamaan reguler memiliki jangkar untuk permulaan (yaitu ^) dari sebuah string dan merupakan pencocokan yang peka huruf besar / kecil "
Ryan Schumacher
2
Dengan Mongoose ini berhasil untuk saya: User.find ({'username': {$ regex: new RegExp ('^' + username.toLowerCase (), 'i')}}, function (err, res) {if (err ) melempar err; next (null, res);});
ChrisRich
5
Jangan pernah lupa untuk mengosongkan nama saat bekerja dengan ekspresi reguler. Kami tidak ingin suntikan mengambil alih keindahan mongodb. Bayangkan saja Anda menggunakan kode ini untuk halaman login dan nama penggunanya adalah ".*".
Tobias
90
Anda perlu menggunakan ekspresi reguler tidak peka huruf besar kecil untuk yang satu ini, mis
MongoDB 3.4 sekarang menyertakan kemampuan untuk membuat indeks case-insensitive yang sebenarnya, yang secara dramatis akan meningkatkan kecepatan pencarian case-sensitive pada dataset besar. Itu dibuat dengan menentukan collation dengan kekuatan 2.
Mungkin cara termudah untuk melakukannya adalah dengan mengatur pemeriksaan pada database. Kemudian semua kueri mewarisi pemeriksaan itu dan akan menggunakannya:
Ekspresi reguler lebih lambat daripada pencocokan string literal. Namun, bidang huruf kecil tambahan akan meningkatkan kompleksitas kode Anda. Jika ragu, gunakan ekspresi reguler. Saya akan menyarankan untuk hanya menggunakan bidang huruf kecil secara eksplisit jika itu dapat menggantikan bidang Anda, yaitu, Anda tidak peduli tentang kasus di tempat pertama.
Perhatikan bahwa Anda harus keluar dari nama sebelum regex. Jika Anda menginginkan karakter pengganti masukan pengguna, lebih suka menambahkan .replace(/%/g, '.*')setelah keluar sehingga Anda dapat mencocokkan "a%" untuk menemukan semua nama yang dimulai dengan 'a'.
Contoh berikut membuat koleksi tanpa pemeriksaan default, lalu menambahkan indeks pada bidang nama dengan pemeriksaan tidak peka huruf besar / kecil. Komponen Internasional untuk Unicode
/*
* strength: CollationStrength.Secondary
* Secondary level of comparison. Collation performs comparisons up to secondary * differences, such as diacritics. That is, collation performs comparisons of
* base characters (primary differences) and diacritics (secondary differences). * Differences between base characters takes precedence over secondary
* differences.
*/
db.users.createIndex( { name: 1 }, collation: { locale: 'tr', strength: 2 } } )
Untuk menggunakan indeks, kueri harus menentukan pemeriksaan yang sama.
db.users.insert( [ { name: "Oğuz" },
{ name: "oğuz" },
{ name: "OĞUZ" } ] )
// does not use index, finds one result
db.users.find( { name: "oğuz" } )
// uses the index, finds three results
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 2 } )
// does not use the index, finds three results (different strength)
db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 1 } )
atau Anda dapat membuat koleksi dengan pemeriksaan default:
Jawaban:
Solusi Chris Fulstow akan berfungsi (+1), namun, mungkin tidak efisien, terutama jika koleksi Anda sangat besar. Ekspresi reguler yang tidak di-root (yang tidak diawali dengan
^
, yang menambatkan ekspresi reguler ke awal string), dan ekspresi reguler yang menggunakani
tanda untuk ketidaksensitifan huruf besar / kecil tidak akan menggunakan indeks, meskipun ada.Opsi alternatif yang dapat Anda pertimbangkan adalah mendenormalisasi data Anda untuk menyimpan
name
bidang versi huruf kecil , misalnya sebagainame_lower
. Anda kemudian dapat membuat kueri yang efisien (terutama jika diindeks) untuk pencocokan tepat tidak peka huruf besar / kecil seperti:db.collection.find({"name_lower": thename.toLowerCase()})
Atau dengan pencocokan awalan (ekspresi reguler yang di-root) sebagai:
db.collection.find( {"name_lower": { $regex: new RegExp("^" + thename.toLowerCase(), "i") } } );
Kedua kueri ini akan menggunakan indeks di
name_lower
.sumber
new RegExp('^'+ username + '$', "i")
agar sama persis.".*"
.Anda perlu menggunakan ekspresi reguler tidak peka huruf besar kecil untuk yang satu ini, mis
db.collection.find( { "name" : { $regex : /Andrew/i } } );
Untuk menggunakan pola regex dari
thename
variabel Anda , buat objek RegExp baru :var thename = "Andrew"; db.collection.find( { "name" : { $regex : new RegExp(thename, "i") } } );
Update: Untuk pencocokan tepat, Anda harus menggunakan regex
"name": /^Andrew$/i
. Terima kasih kepada Yannick L.sumber
name
, tidak hanya menyamakan.{ "name": /^Andrew$/i }
Saya telah menyelesaikannya seperti ini.
var thename = 'Andrew'; db.collection.find({'name': {'$regex': thename,$options:'i'}});
Jika Anda ingin menanyakan tentang 'pencocokan persis tidak peka huruf besar / kecil' maka Anda dapat melakukannya seperti ini.
var thename = '^Andrew$'; db.collection.find({'name': {'$regex': thename,$options:'i'}});
sumber
MongoDB 3.4 sekarang menyertakan kemampuan untuk membuat indeks case-insensitive yang sebenarnya, yang secara dramatis akan meningkatkan kecepatan pencarian case-sensitive pada dataset besar. Itu dibuat dengan menentukan collation dengan kekuatan 2.
Mungkin cara termudah untuk melakukannya adalah dengan mengatur pemeriksaan pada database. Kemudian semua kueri mewarisi pemeriksaan itu dan akan menggunakannya:
db.createCollection("cities", { collation: { locale: 'en_US', strength: 2 } } ) db.names.createIndex( { city: 1 } ) // inherits the default collation
Anda juga bisa melakukannya seperti ini:
db.myCollection.createIndex({city: 1}, {collation: {locale: "en", strength: 2}});
Dan gunakan seperti ini:
db.myCollection.find({city: "new york"}).collation({locale: "en", strength: 2});
Ini akan mengembalikan kota bernama "new york", "New York", "New york", dll.
Untuk info lebih lanjut: https://jira.mongodb.org/browse/SERVER-90
sumber
Dengan Mongoose (dan Node), ini berhasil:
User.find({ email: /^[email protected]$/i })
User.find({ email: new RegExp(
`^ $ {emailVariable} $`, 'i')})Di MongoDB, ini berhasil:
db.users.find({ email: { $regex: /^[email protected]$/i }})
Kedua baris peka huruf besar / kecil. Email di DB bisa jadi
[email protected]
dan kedua baris tersebut masih akan menemukan objek di DB.Demikian juga, kami dapat menggunakan
/^[email protected]$/i
dan masih akan menemukan email:[email protected]
di DB.sumber
Untuk menemukan string case Insensitive gunakan ini,
var thename = "Andrew"; db.collection.find({"name":/^thename$/i})
sumber
Saya baru saja menyelesaikan masalah ini beberapa jam yang lalu.
var thename = 'Andrew' db.collection.find({ $text: { $search: thename } });
Anda bahkan dapat mengembangkannya dengan memilih bidang yang Anda butuhkan dari objek pengguna Andrew dengan cara ini:
db.collection.find({ $text: { $search: thename } }).select('age height weight');
Referensi: https://docs.mongodb.org/manual/reference/operator/query/text/#text
sumber
... dengan luwak di NodeJS kueri itu:
const countryName = req.params.country; { 'country': new RegExp(`^${countryName}$`, 'i') };
atau
const countryName = req.params.country; { 'country': { $regex: new RegExp(`^${countryName}$`), $options: 'i' } }; // ^australia$
atau
const countryName = req.params.country; { 'country': { $regex: new RegExp(`^${countryName}$`, 'i') } }; // ^turkey$
Contoh kode lengkap dalam Javascript, NodeJS dengan Mongoose ORM di MongoDB
// get all customers that given country name app.get('/customers/country/:countryName', (req, res) => { //res.send(`Got a GET request at /customer/country/${req.params.countryName}`); const countryName = req.params.countryName; // using Regular Expression (case intensitive and equal): ^australia$ // const query = { 'country': new RegExp(`^${countryName}$`, 'i') }; // const query = { 'country': { $regex: new RegExp(`^${countryName}$`, 'i') } }; const query = { 'country': { $regex: new RegExp(`^${countryName}$`), $options: 'i' } }; Customer.find(query).sort({ name: 'asc' }) .then(customers => { res.json(customers); }) .catch(error => { // error.. res.send(error.message); }); });
sumber
Kueri berikut akan menemukan dokumen dengan string yang diperlukan secara tidak sensitif dan dengan kejadian global juga
db.collection.find({name:{ $regex: new RegExp(thename, "ig") } },function(err, doc) { //Your code here... });
sumber
Untuk menemukan string literal peka huruf besar kecil:
Menggunakan regex (disarankan)
db.collection.find({ name: { $regex: new RegExp('^' + name.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + '$', 'i') } });
Menggunakan indeks huruf kecil (lebih cepat)
db.collection.find({ name_lower: name.toLowerCase() });
Ekspresi reguler lebih lambat daripada pencocokan string literal. Namun, bidang huruf kecil tambahan akan meningkatkan kompleksitas kode Anda. Jika ragu, gunakan ekspresi reguler. Saya akan menyarankan untuk hanya menggunakan bidang huruf kecil secara eksplisit jika itu dapat menggantikan bidang Anda, yaitu, Anda tidak peduli tentang kasus di tempat pertama.
Perhatikan bahwa Anda harus keluar dari nama sebelum regex. Jika Anda menginginkan karakter pengganti masukan pengguna, lebih suka menambahkan
.replace(/%/g, '.*')
setelah keluar sehingga Anda dapat mencocokkan "a%" untuk menemukan semua nama yang dimulai dengan 'a'.sumber
Anda dapat menggunakan Indeks Kasus Tidak Peka :
Contoh berikut membuat koleksi tanpa pemeriksaan default, lalu menambahkan indeks pada bidang nama dengan pemeriksaan tidak peka huruf besar / kecil. Komponen Internasional untuk Unicode
/* * strength: CollationStrength.Secondary * Secondary level of comparison. Collation performs comparisons up to secondary * differences, such as diacritics. That is, collation performs comparisons of * base characters (primary differences) and diacritics (secondary differences). * Differences between base characters takes precedence over secondary * differences. */ db.users.createIndex( { name: 1 }, collation: { locale: 'tr', strength: 2 } } )
Untuk menggunakan indeks, kueri harus menentukan pemeriksaan yang sama.
db.users.insert( [ { name: "Oğuz" }, { name: "oğuz" }, { name: "OĞUZ" } ] ) // does not use index, finds one result db.users.find( { name: "oğuz" } ) // uses the index, finds three results db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 2 } ) // does not use the index, finds three results (different strength) db.users.find( { name: "oğuz" } ).collation( { locale: 'tr', strength: 1 } )
atau Anda dapat membuat koleksi dengan pemeriksaan default:
db.createCollection("users", { collation: { locale: 'tr', strength: 2 } } ) db.users.createIndex( { name : 1 } ) // inherits the default collation
sumber
Cara yang mudah adalah dengan menggunakan $ toLower seperti di bawah ini.
db.users.aggregate([ { $project: { name: { $toLower: "$name" } } }, { $match: { name: the_name_to_search } } ])
sumber