Untuk MongoDB 3.6 dan yang lebih baru:
$expr
operator mengizinkan penggunaan ekspresi agregasi dalam bahasa kueri, sehingga Anda dapat memanfaatkan penggunaan $strLenCP
operator untuk memeriksa panjang string sebagai berikut:
db.usercollection.find({
"name": { "$exists": true },
"$expr": { "$gt": [ { "$strLenCP": "$name" }, 40 ] }
})
Untuk MongoDB 3.4 dan yang lebih baru:
Anda juga dapat menggunakan kerangka kerja agregasi dengan $redact
operator pipa yang memungkinkan Anda untuk memproses kondisi logis dengan $cond
operator dan menggunakan operasi khusus $$KEEP
untuk "menyimpan" dokumen dengan kondisi logika benar atau $$PRUNE
untuk "menghapus" dokumen yang kondisinya salah.
Operasi ini mirip dengan memiliki $project
pipa yang memilih bidang dalam koleksi dan membuat bidang baru yang menyimpan hasil dari kueri kondisi logis dan kemudian $match
berikutnya , kecuali $redact
menggunakan satu tahap pipeline yang lebih efisien.
Untuk kondisi logikanya, ada String Aggregation Operator yang bisa digunakan $strLenCP
operator untuk memeriksa panjang string. Jika panjangnya $gt
nilai yang ditentukan, maka ini adalah kecocokan yang sebenarnya dan dokumen "disimpan". Jika tidak, "dipangkas" dan dibuang.
Pertimbangkan untuk menjalankan operasi agregat berikut yang menunjukkan konsep di atas:
db.usercollection.aggregate([
{ "$match": { "name": { "$exists": true } } },
{
"$redact": {
"$cond": [
{ "$gt": [ { "$strLenCP": "$name" }, 40] },
"$$KEEP",
"$$PRUNE"
]
}
},
{ "$limit": 2 }
])
Jika menggunakan $where
, coba kueri Anda tanpa tanda kurung:
db.usercollection.find({$where: "this.name.length > 40"}).limit(2);
Permintaan yang lebih baik adalah memeriksa keberadaan bidang dan kemudian memeriksa panjangnya:
db.usercollection.find({name: {$type: 2}, $where: "this.name.length > 40"}).limit(2);
atau:
db.usercollection.find({name: {$exists: true}, $where: "this.name.length >
40"}).limit(2);
MongoDB mengevaluasi non-$where
operasi kueri sebelum $where
ekspresi dan non-$where
pernyataan kueri dapat menggunakan indeks. Performa yang jauh lebih baik adalah menyimpan panjang string sebagai bidang lain dan kemudian Anda dapat mengindeks atau mencarinya; menerapkan $where
akan jauh lebih lambat dibandingkan dengan itu. Disarankan untuk menggunakan ekspresi JavaScript dan $where
operator sebagai upaya terakhir saat Anda tidak dapat menyusun data dengan cara lain, atau saat Anda berurusan dengan sebagian kecil data.
Pendekatan berbeda dan lebih cepat yang menghindari penggunaan $where
operatornya adalah $regex
operator. Perhatikan pola berikut yang mencari
db.usercollection.find({"name": {"$type": 2, "$regex": /^.{41,}$/}}).limit(2);
Catatan - Dari dokumen :
Jika ada indeks untuk bidang tersebut, maka MongoDB mencocokkan ekspresi reguler dengan nilai dalam indeks, yang bisa lebih cepat daripada pemindaian koleksi. Optimalisasi lebih lanjut dapat terjadi jika ekspresi reguler adalah "ekspresi awalan", yang berarti bahwa semua potensi pencocokan dimulai dengan string yang sama. Hal ini memungkinkan MongoDB untuk membuat "rentang" dari awalan itu dan hanya cocok dengan nilai-nilai dari indeks yang termasuk dalam rentang itu.
Ekspresi reguler adalah "ekspresi awalan" jika dimulai dengan acaret
(^)
atau jangkar kiri(\A)
, diikuti oleh serangkaian simbol sederhana. Misalnya, regex/^abc.*/
akan dioptimalkan dengan mencocokkan hanya dengan nilai dari indeks yang dimulai denganabc
.Selain itu, while
/^a/, /^a.*/,
dan/^a.*$/
cocok dengan string yang setara, mereka memiliki karakteristik kinerja yang berbeda. Semua ekspresi ini menggunakan indeks jika ada indeks yang sesuai; namun,/^a.*/
, dan/^a.*$/
lebih lambat./^a/
dapat berhenti memindai setelah mencocokkan awalan.