Semua yang ada di dalam $expr
adalah ekspresi agregasi, dan dokumentasi tidak boleh "mengatakan Anda tidak bisa secara eksplisit" , tetapi kurangnya nama operator
dan Masalah JIRA SERVER-11947
pasti mengatakan itu. Jadi jika Anda membutuhkan ekspresi reguler maka Anda benar-benar tidak memiliki pilihan lain selain menggunakan $where
sebagai gantinya:
db.getCollection('permits').find({
"$where": function() {
var description = this.inspections
.sort((a,b) => b.inspectionDate.valueOf() - a.inspectionDate.valueOf())
.shift().description;
return /^Found a .* at the property$/.test(description) ||
description === "Health Inspection";
}
})
Anda masih dapat menggunakan $expr
dan ekspresi agregasi untuk pencocokan persis, atau simpan saja perbandingan dalam $where
omong-omong. Tetapi saat ini satu-satunya ekspresi reguler yang dipahami MongoDB adalah $regex
dalam ekspresi "query"
.
Jika Anda benar-benar "memerlukan" ekspresi pipeline agregasi yang menghalangi Anda menggunakan $where
, maka satu-satunya pendekatan yang valid saat ini adalah pertama-tama "memproyeksikan" bidang secara terpisah dari larik dan kemudian $match
dengan ekspresi kueri reguler:
db.getCollection('permits').aggregate([
{ "$addFields": {
"lastDescription": {
"$arrayElemAt": [
"$inspections.description",
{ "$indexOfArray": [
"$inspections.inspectionDate",
{ "$max": "$inspections.inspectionDate" }
]}
]
}
}},
{ "$match": {
"lastDescription": {
"$in": [/^Found a .* at the property$/,/Health Inspection/]
}
}}
])
Yang membawa kami pada fakta bahwa Anda tampaknya mencari item dalam array dengan nilai tanggal maksimum. Sintaks JavaScript harus memperjelas bahwa pendekatan yang benar di sini adalah $sort
array pada "perbarui". Dengan cara itu item "pertama" dalam array bisa menjadi "terbaru". Dan ini adalah sesuatu yang dapat Anda lakukan dengan kueri biasa.
Untuk mempertahankan urutan, pastikan item baru ditambahkan ke larik dengan $push
dan $sort
seperti ini:
db.getCollection('permits').updateOne(
{ "_id": _idOfDocument },
{
"$push": {
"inspections": {
"$each": [{ /* Detail of inspection object */ }],
"$sort": { "inspectionDate": -1 }
}
}
}
)
Bahkan dengan argumen array kosong ke $each
sebuah updateMany()
akan memperbarui semua dokumen Anda yang ada:
db.getCollection('permits').updateMany(
{ },
{
"$push": {
"inspections": {
"$each": [],
"$sort": { "inspectionDate": -1 }
}
}
}
)
Ini benar-benar hanya diperlukan ketika Anda sebenarnya "mengubah" tanggal yang disimpan selama pembaruan, dan pembaruan tersebut paling baik dikeluarkan dengan bulkWrite()
untuk melakukan "baik" pembaruan dan "sort" array secara efektif:
db.getCollection('permits').bulkWrite([
{ "updateOne": {
"filter": { "_id": _idOfDocument, "inspections._id": indentifierForArrayElement },
"update": {
"$set": { "inspections.$.inspectionDate": new Date() }
}
}},
{ "updateOne": {
"filter": { "_id": _idOfDocument },
"update": {
"$push": { "inspections": { "$each": [], "$sort": { "inspectionDate": -1 } } }
}
}}
])
Namun jika Anda tidak pernah benar-benar "mengubah" tanggal, maka mungkin lebih masuk akal untuk menggunakan $position
pengubah dan "pra-pend" ke array alih-alih "menambahkan", dan menghindari overhead $sort
:
db.getCollection('permits').updateOne(
{ "_id": _idOfDocument },
{
"$push": {
"inspections": {
"$each": [{ /* Detail of inspection object */ }],
"$position": 0
}
}
}
)
Dengan array yang diurutkan secara permanen atau setidaknya dibuat sehingga tanggal "terbaru" sebenarnya selalu merupakan entri "pertama", maka Anda cukup menggunakan ekspresi kueri reguler:
db.getCollection('permits').find({
"inspections.0.description": {
"$in": [/^Found a .* at the property$/,/Health Inspection/]
}
})
Jadi pelajarannya di sini adalah jangan mencoba dan memaksakan ekspresi yang dihitung pada logika Anda di mana Anda benar-benar tidak perlu melakukannya. Seharusnya tidak ada alasan kuat mengapa Anda tidak dapat mengurutkan konten larik sebagai "disimpan" untuk memiliki "tanggal terbaru pertama " , dan bahkan jika Anda merasa membutuhkan array dalam urutan lain, Anda mungkin harus mempertimbangkan kasus penggunaan mana yang lebih penting.
Setelah diurutkan ulang, Anda bahkan dapat memanfaatkan indeks sampai batas tertentu selama ekspresi reguler ditambatkan ke awal string atau setidaknya sesuatu yang lain dalam ekspresi kueri melakukan pencocokan persis.
Jika Anda merasa benar-benar tidak dapat menyusun ulang array, maka $where
kueri adalah satu-satunya pilihan Anda saat ini hingga masalah JIRA teratasi. Yang mudah-mudahan sebenarnya untuk rilis 4.1 seperti yang ditargetkan saat ini, tapi itu lebih dari kemungkinan 6 bulan hingga satu tahun pada perkiraan terbaik.