Anda tampaknya berpikir bahwa mungkin untuk memanggil fungsi JavaScript dalam pipa agregasi, tetapi Anda tidak dapat melakukan ini. Anda salah mengartikan apa yang sebenarnya "interpolasi" variabel dari hasil fungsi untuk eksekusi dalam pipa.
Misalnya Jika saya melakukan ini:
var getNumbers = function() { return [ 1,2,3 ] };
Lalu saya menyebutnya:
db.collection.aggregate([
{ "$project": {
"mynums": getNumbers()
}}
])
Lalu apa yang sebenarnya terjadi di JavaScript shell nilai-nilai tersebut sedang "diinterpolasi" dan "sebelum" instruksi tersebut dikirim ke server, seperti ini:
db.collection.aggregate([
{ "$project": {
"mynums": [1,2,3]
}}
])
Untuk mendemonstrasikan lebih lanjut, simpan fungsi "hanya" di server:
db.system.js.save({ "_id": "hello", "value": function() { return "hello" } })
Kemudian coba jalankan pernyataan agregasi:
db.collection.aggregate([
{ "$project": {
"greeting": hello()
}}
])
Dan itu akan menghasilkan pengecualian:
E QUERY [main] ReferenceError:hello tidak didefinisikan di (shell)::1:69
Itu karena eksekusi terjadi pada "klien" dan bukan "server" dan fungsi tidak ada pada klien.
Kerangka kerja agregasi tidak bisa jalankan JavaScript, karena tidak memiliki ketentuan untuk melakukannya. Semua operasi dilakukan dalam kode asli, tanpa mesin JavaScript yang dipanggil. Karenanya Anda menggunakan operator di sana sebagai gantinya:
db.collection.aggregate([
{ "$project": {
"total": { "$add": [ 1, 2 ] },
"field_total": { "$subtract": [ "$gross", "$tax" ] }
}}
])
Jika Anda tidak dapat menggunakan operator untuk mencapai hasil, maka satu-satunya cara Anda dapat menjalankan kode JavaScript adalah dengan menjalankan mapReduce sebagai gantinya, yang tentu saja menggunakan mesin JavaScript untuk berinteraksi dengan data dari koleksi. Dan dari sana Anda juga dapat merujuk fungsi sisi server di dalam logika Anda jika Anda perlu:
{ "key": 1, "value": 1 },
{ "key": 1, "value": 2 },
{ "key": 1, "value": 3 }
db.system.js.save({ "_id": "square", "value": function(num) { return num * num } })
db.collection.mapReduce(
function() {
emit(this.key,square(this.value))
},
function(key,values) {
return Array.sum(values);
},
{ "out": { "inline": 1 } }
)
Pengembalian:
{
"_id": 1,
"value": 14
}
Jadi ini bukan tentang "cara meneruskan nilai bidang" tetapi sebenarnya tentang fakta bahwa kerangka kerja agregasi tidak mendukung JavaScript dengan cara apa pun, dan bahwa apa yang Anda pikir sedang terjadi sebenarnya tidak demikian.