MongoDB
 sql >> Teknologi Basis Data >  >> NoSQL >> MongoDB

Menggunakan fungsi JavaScript yang tersimpan dalam pipa Agregasi, MapReduce atau runCommand

Fungsi apa pun yang Anda simpan ke system.js tersedia untuk digunakan oleh pernyataan pemrosesan "JavaScript" seperti $where operator dan mapReduce dan dapat dirujuk oleh _id nilai telah ditetapkan.

db.system.js.save({ 
   "_id": "squareThis", 
   "value": function(a) { return a*a } 
})

Dan beberapa data dimasukkan ke koleksi "sampel":

{ "_id" : ObjectId("55aafd2bacbed38e06f9eccf"), "a" : 1 }
{ "_id" : ObjectId("55aafea6acbed38e06f9ecd0"), "a" : 2 }
{ "_id" : ObjectId("55aafeabacbed38e06f9ecd1"), "a" : 3 }

Kemudian:

db.sample.mapReduce(
    function() {
       emit(null, squareThis(this.a));
    },
    function(key,values) {
        return Array.sum(values);
    },
    { "out": { "inline": 1 } }
 );

Memberikan:

   "results" : [
            {
                    "_id" : null,
                    "value" : 14
            }
    ],

Atau dengan $where :

db.sample.find(function() { return squareThis(this.a) == 9 })
{ "_id" : ObjectId("55aafeabacbed38e06f9ecd1"), "a" : 3 }

Tetapi dalam kasus "tidak keduanya" Anda dapat menggunakan global seperti database db referensi atau fungsi lainnya. Keduanya $where dan mapReduce dokumentasi berisi informasi tentang batasan apa yang dapat Anda lakukan di sini. Jadi, jika Anda berpikir akan melakukan sesuatu seperti "mencari data di koleksi lain", Anda dapat melupakannya karena "Tidak Diizinkan".

Setiap Tindakan perintah MongoDB sebenarnya panggilan ke tindakan "runCommand" "di bawah tenda". Tetapi kecuali apa yang sebenarnya dilakukan oleh perintah itu adalah "memanggil mesin pemrosesan JavaScript" maka penggunaannya menjadi tidak relevan. Hanya ada beberapa perintah yang melakukan ini, yaitu mapReduce , group atau eval , dan tentu saja operasi find dengan $where .

Kerangka kerja agregasi tidak gunakan JavaScript dengan cara apa pun. Anda mungkin salah seperti orang lain telah melakukan pernyataan seperti ini, yang tidak melakukan apa yang Anda pikirkan:

db.sample.aggregate([
    { "$match": {
        "a": { "$in": db.sample.distinct("a") }
    }}
])

Jadi itu "tidak berjalan di dalam " pipa agregasi, melainkan "hasil" dari .distinct() . itu panggilan "dievaluasi" sebelum pipa dikirim ke server. Sama seperti dengan variabel eksternal dilakukan pula:

var items = [1,2,3];
db.sample.aggregate([
    { "$match": {
        "a": { "$in": items }
    }}
])

Keduanya pada dasarnya mengirim ke server dengan cara yang sama:

db.sample.aggregate([
    { "$match": {
        "a": { "$in": [1,2,3] }
    }}
])

Jadi "tidak mungkin" untuk "memanggil" fungsi JavaScript apa pun dalam pipa agregasi, juga tidak ada gunanya "melewati" hasil secara umum dari sesuatu yang disimpan di system.js . "Kode" perlu "dimuat ke klien" dan hanya mesin JavaScript yang benar-benar dapat melakukan apa pun dengannya.

Dengan kerangka kerja agregasi, semua "operator" yang tersedia sebenarnya adalah fungsi kode asli yang bertentangan dengan interpretasi JavaScript "bentuk bebas" yang disediakan untuk mapReduce . Jadi, alih-alih menulis "JavaScript", Anda menggunakan operator itu sendiri:

db.sample.aggregate([
    { "$group": {
        "_id": null,
        "sqared": { "$sum": {
           "$multiply": [ "$a", "$a" ]
        }}
    }}
])

{ "_id" : null, "sqared" : 14 }

Jadi ada batasan pada apa yang dapat Anda lakukan dengan fungsi yang disimpan di system.js, dan kemungkinan yang ingin Anda lakukan adalah:

  • Tidak diizinkan, seperti mengakses data dari koleksi lain
  • Tidak terlalu diperlukan karena logika umumnya mandiri
  • Atau mungkin lebih baik diimplementasikan dalam logika klien atau bentuk lain yang berbeda

Satu-satunya penggunaan praktis yang benar-benar dapat saya pikirkan adalah bahwa Anda memiliki sejumlah operasi "mapReduce" yang tidak dapat dilakukan dengan cara lain dan Anda memiliki berbagai fungsi "bersama" yang lebih suka Anda simpan di server daripada dipertahankan di setiap panggilan fungsi mapReduce.

Tetapi sekali lagi, 90% alasan mapReduce di atas kerangka agregasi biasanya karena "struktur dokumen" dari koleksi telah dipilih dengan buruk dan fungsionalitas JavaScript "diperlukan" untuk melintasi dokumen untuk pencarian dan analisis.

Jadi Anda dapat menggunakannya di bawah batasan yang diizinkan, tetapi dalam banyak kasus Anda mungkin tidak boleh menggunakan ini sama sekali, tetapi memperbaiki masalah lain yang membuat Anda yakin bahwa Anda membutuhkan fitur ini sejak awal.




  1. Redis
  2.   
  3. MongoDB
  4.   
  5. Memcached
  6.   
  7. HBase
  8.   
  9. CouchDB
  1. MongoDB $setOnInsert

  2. MongoDb - Ubah jenis dari Int menjadi Double

  3. Bagaimana kita bisa membuat bidang yang dihasilkan otomatis untuk mongodb menggunakan boot pegas

  4. String luwak ke ObjectID

  5. Cara terbaik untuk memodelkan sistem pemungutan suara di MongoDB