Jika Anda ingin "membobot" hasil dengan kriteria tertentu atau memiliki "nilai yang dihitung" dalam "sort", maka Anda memerlukan .aggregate()
metode sebagai gantinya. Ini memungkinkan nilai "yang diproyeksikan" untuk digunakan dalam $sort
operasi, yang hanya dapat digunakan bidang saat ini dalam dokumen:
db.messages.aggregate([
{ "$match": { "messages": userId } },
{ "$project": {
"recipients": 1,
"unread": 1,
"content": 1,
"readYet": {
"$setIsSubset": [ [userId], "$unread" ] }
}
}},
{ "$sort": { "readYet": -1 } },
{ "$limit": 20 }
])
Di sini $setIsSubset
operator memungkinkan perbandingan larik "belum dibaca" dengan larik konversi [userId]
untuk melihat apakah ada kecocokan. Hasilnya akan menjadi true
di mana userId ada atau false
di mana tidak.
Ini kemudian dapat diteruskan ke $sort
, yang mengurutkan hasil dengan preferensi kecocokan ( pengurutan menurun adalah true
di atas ), dan terakhir $limit
hanya mengembalikan hasil hingga jumlah yang ditentukan.
Jadi untuk menggunakan istilah yang dihitung untuk "sort", nilainya perlu "diproyeksikan" ke dalam dokumen sehingga dapat diurutkan. Kerangka kerja agregasi adalah cara Anda melakukannya.
Perhatikan juga bahwa $elemMatch
tidak diperlukan hanya untuk mencocokkan satu nilai dalam array, dan Anda hanya perlu menentukan nilai secara langsung. Tujuannya adalah di mana kondisi "banyak" harus dipenuhi pada elemen larik tunggal, yang tentu saja tidak berlaku di sini.