Jika Anda menginginkan batasan semacam itu dalam kueri, maka pada dasarnya Anda memiliki dua opsi tergantung pada apa yang didukung oleh versi MongoDB Anda:
MongoDB 3.6
Anda sebaiknya menggunakan $expr
"selain itu" ke kondisi kueri normal apa pun untuk benar-benar memilih dokumen yang valid:
var A = 10, B = 40;
Model.find({
"subDocs.value": { "$all": [A, B] },
"$expr": {
"$lt": [
{ "$arrayElemAt": [
"$subDocs.index",
{ "$indexOfArray": [ "$subDocs.value", A ]}
]},
{ "$arrayElemAt": [
"$subDocs.index",
{ "$indexOfArray": [ "$subDocs.value", B ]}
]}
]
}
})
Atau mencocokkan "terakhir" kejadian:
Model.find({
"subDocs.value": { "$all": [A, B] },
"$expr": {
"$lt": [
{ "$arrayElemAt": [
"$subDocs.index",
{ "$subtract": [
{ "$subtract": [{ "$size": "$subDocs.value" }, 1 ] },
{ "$indexOfArray": [ { "$reverseArray": "$subDocs.value" }, A ] }
]}
]},
{ "$arrayElemAt": [
"$subDocs.index",
{ "$subtract": [
{ "$subtract": [{ "$size": "$subDocs.value" }, 1 ] },
{ "$indexOfArray": [ { "$reverseArray": "$subDocs.value" }, B ] }
]}
]}
]
}
})
Versi Sebelumnya
Hal yang sama, tetapi tanpa operator asli Anda perlu menggunakan evaluasi JavaScript $where
:
var A = 10, B = 40;
Model.find({
"subDocs.value": { "$all": [A, B] },
"$where": `this.subDocs.find( e => e.value === ${A}).index
< this.subDocs.find( e => e.value === ${B}).index`
})
Atau mencocokkan "terakhir" kejadian:
Model.find({
"subDocs.value": { "$all": [10,40] },
"$where": `let arr = this.subDocs.reverse();
return arr.find( e => e.value === ${A}).index
> arr.find( e => e.value === ${B}).index`
})
Jika Anda membutuhkannya dalam pipeline agregasi, Anda akan menggunakan $redact
dan logika yang mirip dengan contoh pertama sebagai gantinya:
var A = 10, B = 40;
Model.aggregate([
{ "$match": { "subDocs.value": { "$all": [A, B] } } },
{ "$redact": {
"$cond": {
"if": {
"$lt": [
{ "$arrayElemAt": [
"$subDocs.index",
{ "$indexOfArray": [ "$subDocs.value", A ]}
]},
{ "$arrayElemAt": [
"$subDocs.index",
{ "$indexOfArray": [ "$subDocs.value", B ]}
]}
]
},
"then": "$$KEEP",
"else": "$$PRUNE"
}
}}
])
Cukuplah untuk mengatakan bahwa "logika perbandingan" sebenarnya bukan asli dari "ekspresi operator kueri" itu sendiri, jadi satu-satunya bagian yang "secara optimal" dapat diterapkan ke indeks menggunakan $all
operator kueri dalam semua kasus. Logika penting yang tersisa sebenarnya berlaku "setelah" ekspresi utama dievaluasi dan "di samping" agar tidak ada hasil yang dikembalikan selain yang memenuhi ekspresi dengan $expr
atau $where
.
Logika dasar masing-masing pada dasarnya adalah untuk mengekstrak nilai "index"
properti dari anggota array "pertama" yang benar-benar cocok dengan nilai masing-masing dalam "value"
Properti. Dimana ini adalah "kurang dari", maka kondisinya adalah true
dan ini memenuhi dokumen yang dikembalikan.
Jadi perhatikan bahwa "evaluasi yang dihitung" cocok dengan efisiensi operator kueri, dan tanpa digunakan "dalam kombinasi" dari kondisi operator kueri lain yang dapat mengakses "indeks", maka "pemindaian koleksi lengkap" akan dimulai.
Tetapi hasil keseluruhan tentu lebih efisien daripada mengembalikan semua item yang cocok ke kondisi kueri pertama dan kemudian menolaknya pada kursor "setelah" kembali dari database.
Lihat juga dokumentasi untuk $arrayElemAt
, $indexOfArray
, $lt
dan Array.find()
untuk JavaScript