Masalah dasar dengan apa yang Anda tanyakan di sini bermuara pada fakta bahwa data yang dimaksud berada dalam "array", dan oleh karena itu ada beberapa asumsi dasar yang dibuat oleh MongoDB tentang bagaimana hal ini ditangani.
Jika Anda menerapkan pengurutan dalam "urutan menurun", maka MongoDB akan melakukan persis seperti yang Anda minta dan mengurutkan dokumen menurut nilai "terbesar" dari bidang yang ditentukan dalam larik:
.sort({ "revisions.created": -1 ))
Tetapi jika Anda mengurutkan dalam urutan "naik", tentu saja kebalikannya yang benar dan nilai "terkecil" dianggap.
.sort({ "revisions.created": 1 })
Jadi satu-satunya cara untuk melakukan ini berarti menentukan tanggal maksimum dari data dalam array, dan kemudian mengurutkan hasil tersebut. Ini pada dasarnya berarti menerapkan .aggregate()
, yang untuk meteor adalah operasi sisi server, sayangnya seperti ini:
Collection.aggregate([
{ "$unwind": "$revisions" },
{ "$group": {
"_id": "$_id",
"name": { "$first": "$name" },
"revisions": { "$push": "$revisions" },
"number": { "$first": "$number" }
"maxDate": { "$max": "$revisions.created" }
}},
{ "$sort": { "maxDate": 1 }
])
Atau paling baik dengan MongoDB 3.2, di mana $max
dapat diterapkan langsung ke ekspresi array:
Collection.aggregate([
{ "$project": {
"name": 1,
"revisions": 1,
"number": 1,
"maxDate": {
"$max": {
"$map": {
"input": "$revisions",
"as": "el",
"in": "$$el.created"
}
}
}
}},
{ "$sort": { "maxDate": 1 } }
])
Tetapi sebenarnya keduanya tidak terlalu bagus, bahkan jika pendekatan MongoDB 3.2 memiliki overhead yang jauh lebih sedikit daripada yang tersedia untuk versi sebelumnya, itu masih tidak sebagus yang Anda dapatkan dalam hal kinerja karena kebutuhan untuk melewati data dan pekerjaan keluar nilai untuk diurutkan.
Jadi untuk terbaik kinerja, "selalu" simpan data yang Anda perlukan "di luar" dari array. Untuk ini ada $max
operator "update", yang hanya akan mengganti nilai dalam dokumen "jika" nilai yang diberikan "lebih besar dari" nilai yang sudah ada di sana. yaitu:
Collection.update(
{ "_id": "qTF8kEphNoB3eTNRA" },
{
"$push": {
"revisions": { "created": new Date("2016-02-01") }
},
"$max": { "maxDate": new Date("2016-02-01") }
}
)
Ini berarti bahwa nilai yang Anda inginkan akan "selalu" sudah ada di dalam dokumen dengan nilai yang diharapkan, jadi sekarang tinggal menyortir bidang tersebut:
.sort({ "maxDate": 1 })
Jadi untuk uang saya, saya akan menggunakan data yang ada dengan salah satu dari .aggregate()
pernyataan yang tersedia, dan gunakan hasil tersebut untuk memperbarui setiap dokumen agar berisi bidang "maxDate". Kemudian ubah coding semua penambahan dan revisi data array untuk menerapkan $max
"perbarui" pada setiap perubahan.
Memiliki bidang yang solid daripada perhitungan selalu lebih masuk akal jika Anda cukup sering menggunakannya. Dan perawatannya cukup sederhana.
Bagaimanapun, mengingat tanggal contoh yang diterapkan di atas, yang "kurang dari" tanggal maksimum lainnya yang ada akan kembali untuk saya dalam segala bentuk:
{
"_id" : "5xF9iDTj3reLDKNHh",
"name" : "Lorem ipsum",
"revisions" : [
{
"number" : 0,
"comment" : "Dolor sit amet",
"created" : ISODate("2016-02-11T01:22:45.588Z")
}
],
"number" : 1,
"maxDate" : ISODate("2016-02-11T01:22:45.588Z")
}
{
"_id" : "qTF8kEphNoB3eTNRA",
"name" : "Consecitur quinam",
"revisions" : [
{
"comment" : "Hoste ad poderiquem",
"number" : 1,
"created" : ISODate("2016-02-11T23:25:46.033Z")
},
{
"number" : 0,
"comment" : "Fagor questibilus",
"created" : ISODate("2016-02-11T01:22:45.588Z")
},
{
"created" : ISODate("2016-02-01T00:00:00Z")
}
],
"number" : 2,
"maxDate" : ISODate("2016-02-11T23:25:46.033Z")
}
Yang dengan benar menempatkan dokumen pertama di atas urutan pengurutan dengan mempertimbangkan "maxDate".