Pendahuluan MongoDB – The NoSQL Document Database


Saat data semakin besar, untuk mempertahankan performanya database relasional haus akan sumber daya (resources). Hal ini berakibat langsung ke membengkaknya cost/biaya operasional & infrastruktur yang dibutuhkan. Sehingga biasanya hanya perusahaan besar yang mampu untuk mempertahankan penggunaan database relasional saat datanya besar. Lebih jauh lagi, saat volume data membesar, format (struktur) data yang disimpan-pun semakin beragam (vary). Karena database relasional memiliki schema/struktur yang tetap (fixed), ia tidak lagi menjadi solusi yang feasible saat hal ini terjadi (minimal sangat menyulitkan).  Teknologi NoSQL seperti MongoDB hadir untuk mengatasi permasalahan di Data dengan Volume (besar data), Velocity (laju pertumbuhan data), & variety (Format data) yang besar dan beragam. Terdapat banyak pilihan teknologi NoSQL yang dapat digunakan (read here), namun kali ini akan dibahas dasar penggunaan NoSQL MongoDB. MongoDB memiliki beberapa kelebihan khusus dibandingkan NoSQL lainnya. Beberapa diantaranya adalah Schemaless, Dynamic Query, “Auto Sharding”, Spatial support, Distributed, Performa yang baik, gratis-open source (AGPL 3), OOP friendly, dan masih banyak lagi.
Di catatan kecil kali ini saya akan membahas tentang pengenalan MongoDB untuk pemula. Saya awali dengan pendahuluan MongoDB,  instalasi MongoDB & utility-nya, lalu sebuah contoh kasus yang akan digunakan sepanjang post ini, kemudian Query, indexing, dan juga tidak ketinggalan Driver MongoDB.

Pendahuluan MongoDB

MongoDB yang berasal dari kata humongous (Besar) adalah sebuah “database” berorientasi dokumen (JSON) yang dapat dijalankan di berbagai sistem operasi (Linux, Windows, Mac, dll). MongoDB sebenarnya tidak menyimpan filenya murni dalam bentuk Json, tapi Bson. Bson adalah bentuk binary dari Json, yang diharapkan memiliki performa lebih baik dari Json (mirip dengan Hadoop & HDFS-nya). Detail lebih lanjut tentang file format Bson dapat dibaca disini. Bagi developer (e.g. Java, C++, & PyThon), format Json/Bson ini lebih OOP friendly.
MongoDB digarap perusahaan MongoDB Inc (dulunya 10gen) sejak 2007. MongoDB baru menjadi project Open Source sejak 2009, dan mulai terkenal ketika nama-nama besar seperti FourSquare, eBay, New York Times, dan Craiglist menggunakan MongoDB di dalam system mereka.  Saat ini MongoDB adalah NoSQL paling popular dibanding pesaing-pesaingnya seperti CouchDB, cassandra, atau Neo4J. Sebagai sistem yang masih relatif muda, tentu saja MongoDB tidak terlepas dari berbagai kekurangan. Namun seiring dengan berjalannya waktu MongoDB telah membuktikan komitmennya untuk terus mengembangkan NoSQL yang terpercaya dan memiliki performa yang mumpuni. Salah satu bentuk kepercayaan yang MongoDB dapatkan adalah suntikan dana besar di tahun 2013 ($150 juta) dan proyeksi bahwa MongoDB akan menjadi bisnis miliaran dollar dalam tempo yang tidak terlalu lama. Prediksi tersebut tidak meleset, di Tahun 2015 MongoDB sudah bernilai $1.6 miliar.
Sebelum kita melangkah lebih jauh, mungkin perbedaan/padanan terminology antara MongoDB dengan terminology di database relasional (e.g. MySQL) berikut dapat memudahkan dalam memahami struktur MongoDB.
Catatan:  Primary key dengan menggunakan Auto Increment id seperti yang biasanya ada di database relasional tidak diperlukan di MongoDB. Setiap dokumen secara automatis akan memiliki field “_id” dan akan di index oleh MongoDB. _id digunakan MongoDB untuk meyakinkan bahwa setiap dokumen memiliki id yang unik. Format _id adalah BSon 12 byte: 4 byte (waktu epoch), 3 byte (machine id), 2 byte (process id), & 3 byte (counter). Contoh nilai _id : "5584aaca21cacd055a1b8fc1". Walau _id bukanlah integer (auto increment), tidak usah hawatir mengakses dokumen dengan urutan tertentu, karena di MongoDB terdapat mekanisme “Natural Order”. Sehingga sebagaimana di database relasional kita bisa menggunakan Limit 50,100 di MongoDB kita juga bisa melakukan hal yang serupa.

Instalasi MongoDB dan RoboMongo

Mari kita mulai dengan cara menginstall MongoDB ver 3 dan RoboMongo di operating system Windows (7/8/10). RoboMongo adalah “PHPMyAdmin”-nya MongoDB, ia digunakan untuk memudahkan proses managemen database di MongoDB. Instalasi MongoDB relatif mudah, namun ada beberapa catatan penting yang perlu diperhatikan. Berikut langkah-langkah dan catatan kecil saya ketika menginstal MongoDB di Windows (Instalasi & implementasi di Linux sebenarnya lebih mudah :) ).
  1. Download versi terakhir MongoDB di link berikut (LINK), dan RoboMongo di Link ini (LINK). Catatan: Jangan salah pilih versi 32bit/64bit. Jika komputer yang digunakan 64bit, sebaiknya unduh yang versi 64bit, versi 32 bit memiliki banyak keterbatasan yang tidak sesuai untuk data yang besar.
  2. TIPS: Saat instalasi pilih “Custom”. Lewat pilihan Custom akan ada pilihan ke folder mana MongoDB akan di-install. Saya pribadi lebih menyukai program-program terpenting di install ke root (misal C:\MongoDB).
  3. Siapkan 3 buah folder lain: data, db, dan log: MisalD:\MongoDB\log\”, “D:\MongoDB\data\”, dan “D:\MongoDB\data\db\”. Catatan: Folder data dan log dapat diletakkan dimana saja, defaultnya adalah “C:\data\db”.  Usahakan untuk meletakkan folder ini di drive dengan space terbanyak (Untuk production/profesional Sebaiknya drive khusus database – NAS).
  4. Tambahkan "C:\MongoDB\Server\3.0\bin" di Path anda [optional].
  5. Install MongoDB sebagai Service: Buka NotePad atau sembarang simple text editor lain. lalu ketikkan perintah-perintah berikut dan save sebagai “mongo.bat”. Sesuaikan dengan Letak data dan Log yang sudah ditetapkan di langkah ke [3]. Atau silahkan unduh filenya DISINI (Karena filenya ".bat" maka browser akan memberikan warning, jangan hawatir filenya hanya berisi perintah -perintah dibawah. If not sure, silahkan buka dengan NotePad untuk memastikan). Jalankan mongo.bat lewat Command Prompt sebagai administrator (Klik kanan icon command prompt lalu pilih run as administrator). “CD”/pindah ke directory dimana mongo.bat tersimpan, lalu jalankan filenya dengan mengetikan “mongo.bat” lalu tekan enter (eksekusi). ==> Yakinkan tidak ada pesan Error. Proses ini hanya dijalankan satu kali saja, tidak perlu dilakukan setiap komputer dinyalakan. echo logpath=D:\MongoDB\log\mongo.log C:\MongoDB\mongod.cfg C:\MongoDB\Server\3.0\bin\mongod.exe--dbpath D:\MongoDB\data\db --config C:\MongoDB\mongod.cfg --install net start MongoDB
  6. Instalasi RoboMongo sangat sederhana, jadi tidak perlu dibahas. Namun, apabila ada kendala silahkan komen dibawah.
  7. Restart [Just to make sure :)]
Cek Koneksi MongoDB: Setelah seluruh langkah diatas dilakukan, ada 2 cara memverifikasi apakah MongoDB telah terinstal dengan baik: [1]. Tombol Windows +R==>”Services.Msc”==> Cek di list service: “mongoDB”, atau [2]. Command Prompt==> “mongo” ==> enter, atau melalui RoboMongo seperti yang akan dijelaskan dibawah ini:
  1. Jalankan (run/eksekusi) RoboMongo.
  2. Pada tampilan awal klik “create
  3. Namakan koneksinya sesuai selera :) … misal “Koneksi_default
  4. Defaultnya MongoDB dapat diakses lewat localhost dengan port 27017, jadi kalau sebelumnya tidak melakukan customize saat instalasi, jangan rubah nilai-nilai ini.
  5. Tekan “save” lalu double click koneksi yang baru saja dibuat.
  6. Jika berhasil akan nampak tampilan ‘seperti’ gambar dibawah. RoboMongo InterfaceBeberapa fungsi dasar juga saya jelaskan di gambar tersebut. Jika tidak berhasil silahkan cek kembali lankah-langkah diatas & ulangi sampai lebaran tahun depan (#kidding :p , komen saja dibawah dan pesan error yang muncul)

Contoh Kasus – Restaurant

Agar lebih mudah dimengerti dan sedekat mungkin ke kasus nyata, akan digunakan sebuah contoh kasus sederhana database restaurant. Sample data ini cukup terkenal, dan juga dijadikan contoh di berbagai NoSQL lain. Datanya dapat di akses melalui URL berikut (Click Here)--Klik kanan dan pilih “save as”. Kalau komputer yang digunakan netbook/komputer yang relatif lambat, silahkan buka file Json-nya dengan notepad, lalu cukup ambil 10 baris (dokumen/json) pertama (Hapus baris ke-11 sampai akhir).
Mari kita masukkan Documents tersebut ke MongoDB. Untuk kemudahan, mari kita gunakan RoboMongo, nanti kita akan bahas memasukkan document lewat query.
  1. Di RoboMongo klik kanan nama koneksi, lalu pilih “create database” ==> namakan “places” (atau sembarang nama lain)
  2. Expand database “places” yang baru saja dibuat, lalu klik kanan “collections” dan pilih “create collection” ==> namakan “restaurants
  3. Klik kanan collection “restaurants” ==> pilih “Insert Documents”
  4. Hapus tanda semua yang ada di layar (tanda “{“ & “}”).
  5. CoPas” Json yang telah di unduh sebelumnya.
  6. Coba validasi JSonnya dengan menekan tombol “validate” di kiri bawah.
  7. Jika semua OK, tekan tombol “save”
Good, sekarang kita siap untuk membahas Query  di mongoDB ... ^_^

Query di MongoDB

Seperti yang sudah dijelaskan di artikel saya sebelumnya, NoSQL bukan berarti kita tidak dapat melakukan query. Di bagian ini kita akan mencoba beberapa cara query untuk mendapatkan informasi dari documents yang telah kita simpan di MongoDB. Query-query di bawah ini bisa dijalankan di MongoDB shell atau menggunakan RoboMongo. Untuk kemudahan (& keindahan tampilan :) ) mari kita gunakan RoboMongo saja. Jalankan RoboMongo dan double klik koleksi “restaurants” seperti gambar diatas. Ketikkan Query-query dibawah ini ke kolom query di RoboMongo, dan jalankan dengan tombol "ctrl+Enter" atau F5. Untuk memudahkan List dari seluruh Query, dapat diunduh di sini (LINK). Dari file Txt tersebut anda bisa "CoPas" query-querynya ke RoboMongo.

Search

  1. show dbs ATAU show collections Untuk menunjukkan semua database ATAU koleksi yang ada.
  2. use places Mengaktifkan query ke database “places”. Catatan di RoboMongo tidak perlu lagi melakukan hal ini jika sebelumnya sudah men-double klik koleksi restaurants.
  3. db.restaurants.find() identik dengan “SELECT * FROM Table” di database relational. Menampilkan semua sebagian data di koleksi.
  4. db.restaurants.find().count() Penambahan “.count()” selalu bisa digunakan di sembarang query utnuk menampilkan banyaknya documen hasil query.
  5. db.restaurants.find( { "borough": "Bronx" } ) Mencari semua restaurant dengan nilai field borough= “Bronx” di koleksi. Catatan: by default di MongoDB pencariannya case sensitive, sehingga jika Bronx dituliskan sebagai “bronx” maka tidak ada data ditemukan (silahkan coba). Hal ini bisa jadi dikarenakan penggunaan format binary-Json (bson). Bisa dikatakan hal ini adalah salah satu kelemahan MongoDB saat ini. Namun seperti yang saya telah sampaikan sebelumnya, MongoDB berkomitmen untuk terus memperbaiki produk mereka. Case insensitive index saat ini (July 2015) sedang dalam tahap pengerjaan (Link). Sementara waktu ada 2 cara bisa dilakukan untuk mengatasi hal ini. Pertama, de-normalisasi data: simpan field yang ingin di akses case insensitive sebagai 2 field yang berbeda (1. original 2.lowercase). Atau cara kedua dengan mengubah Querynya menjadi seperti berikut ini:
  6. db.restaurants.find({borough:/^bronx$/i}) case insensitive search di MongoDB. Catatan: Query menggunakan Regular Expression seperti ini biasanya Jauh lebih lambat. Disarankan untuk menyimpan field tambahan (bentuk lowercase) & cukup meng-index field lowercase ini. Di apps/program yang dilakukan tinggal merubah search query-nya menjadi lowercase (tidak perlu regular expression).
  7. db.restaurants.find({borough:"Bronx"},{cuisine:1}) Defaultnya hasil query di MongoDB menghasilkan semua field di document (high communication cost). Namun tentu saja di aplikasi nyatanya, kita hanya membutuhkan beberapa field tertentu saja. Query diatas hanya menampilkan field “_id” dan field “cuisine”.  Catatan: field _id tetap akan tampil. “1” di “cuisine:1” dapat diganti dengan “-1” untuk merubah urutan dari Ascending (naik) menjadi Descending (menurun).
  8. db.restaurants.find({"grades.0.grade":"B"}) Catatan: field “grades” di koleksi “restaurants” adalah sebuah array dengan sub-fields. Query diatas digunakan untuk mencari data berdasarkan nilai di Array tersebut. Silahkan ber-eksperimen dengan merubah querynya untuk sub-fields yang lain. Apa yang terjadi jika querynya dirubah menjadi “db.restaurants.find({"grades.grade":"B"})” ? … :)
  9. db.restaurants.find({"grades.score":{$lt:5}}) Mencari dokumen dengan nilai grades “kurang dari” 5 dengan operator “less than” ($lt). Catatan: daftar Operator lengkap dapat dilihat di tabel berikut:
  10. db.restaurants.find({$and:[{"cuisine":"Italian"},{"address.zipcode": "10075"}]}) Contoh penggunaan operator berdasarkan dua fields. Catatan: query diatas dapat juga dituliskan tanpa operator $ sebagai “db.restaurants.find({"cuisine":"Italian","address.zipcode":"10075"})
  11. db.restaurants.find({ "cuisine":"Italian"}).sort({"borough":1,"address.zipcode":-1}) Mencari semua retaurants Italia, namun hasilnya diurutkan berdasarkan field borough (ascending), kemudian juga diurutkan berdasarkan field “zipcode” (descending).

Insert

1. Insert sebuah dokumen. Catatan: Jika kita insert, namun databasenya belum ada, maka akan automatis dibuat oleh MongoDB. Perhatikan di contoh insert di bawah saya sengaja menghapus beberapa fields, tujuannya untuk menunjukkan bahwa MongoDB schemaless. Sehingga tidak mengapa field dokumen berbeda-beda. : “db.restaurants.insert({"address":{"street":"2Avenue","coord":[-73.9557413,40.7720266],},"borough":"Manhattan","grades":[{"grade":"A","score":11},{"date":ISODate("2014-01-16T00:00:00Z"),"score":17}],"name":"Vella","restaurant_id":"41704620"})” 2. Multiple (batch) Insert. Query dibawah memasukkan 3 (tiga) dokumen baru. Catatan: nilai _id bisa secara explicit diberikan (walau not Recommended), lagi-lagi jumlah fields tidak sama, dan boleh dengan urutan yang berbeda. db.restaurants.insert([ { _id:11, cuisine:"Sundaan", name:"Mang Jaka", grades: "A" }, { name: "Sedap Malam", grades:"B" }, { name: "Sedap Siang", cuisine:"WarTeg" } ]) 3. Ignore Insert Error. Multiple (batch) insert sangat diminati karena biasanya jauh lebih cepat. Namun rentan akan error. Untuk meng-hiraukan (ignore) insert yang error, gunakan perintah ordered sebagai berikut: db.restaurants.insert([ { _id: 20, name: "WarBet", cusine:"soto", type: "kaki lima" }, { name: "Warung Padang", Grades:"AAA", kapasitas:150 } ],{ ordered: false }) 4. Write Concern. NoSQL sangat cepat, namun tentu saja kelebihan tersebut ada “trade-off”nya. Seperti yang telah dibahas di awal post ini atau di artikel saya sebelumnya, NoSQL seperti MongoDB rentan terhadap insert yang “dangling” (unsafe insert). Namun demikian kita memiliki pilihan di query untuk meyakinkan proses insert tersebut. Query berikut merupakan contoh insert di MongoDB dengan “Write Concern”. Catatan: Pengetahuan ini sangat penting, terutama pada “production level” (aplikasi nyata). Developer harus membedakan berbagai tipe insert agar performa tetap terjaga, namun data penting aman tersimpan di server (ACID compliants). db.products.insert( {item:"envelopes", qty:100, type:"Clasp"}, {writeConcern:{w:"majority", j:true, wtimeout:5000}} ) Option w --(write):
  • 1 (default) ==> wite acknowledgement di mongod (standalone) atau primary replica (jika menggunakan replica set: akan dibahas lebih lanjut di post lain).
  • 0 ==> Disable notification, fastest tapi paling beresiko.
  • 2 (atau 3,4,…)==> "2" artinya insert harus di-acknowledge oleh primary dan “minimal” satu sekunder. 3,4,5,… dan seterusnya analogi dengan 2.
  • majority ==> Mayoritas replica set acknowledge.
  • tag set ==> Karena topik ini masuk “advance” bukan pendahuluan, saya hanya akan berikan contoh saja: {"disk":"ssd","use":"reporting","rack":"d"}
Option j --(journal) : jika nilainya “true” maka MongoDB akan meyakinkan bahwa data akan disimpan ke journal (disk). Artinya jika terjadi “mati listrik” dan mongo ke-shutdown/mati, maka data akan tetap aman, karena telah tersimpan di disk. Gunakan option ini untuk transaksi data yang penting. option wtimeout -- (with Time Out): nilainya dalam milli second (minimal 1, integer). Jika di set “5000” dan dalam 5 detik proses write belum selesai, maka akan return error. WALAUpun sebenarnya eventually akan (partially to some nodes) finished. Make sure you know what are you doing. Karena jika di set 3000 lalu write back message error, bukan berarti datanya belum tersimpan. Jangan gunakan option ini kalau belum mengerti benar.

Update

  1. db.restaurants.update({"name":"Juni"},{$set:{"cuisine":"Sate Tegal"},$currentDate:{"lastModified":true}}) Query diatas mengupdate field Cuisine di dokumen dengan field nama “Juni” . $currentdate adalah operator MongoDB untuk mengakses waktu saat ini (now()). Sehingga field “LastModified” juga di update. Catatan: Hati-hati update dengan cara ini. Update ini  hanya dilakukan pada sebuah Dokumen dengan Field "name=Juni" (Yang pertama kali ditemukan). Sebaiknya update dilakukan dengan indikator field yang unik (id).
  2. db.restaurants.update({"restaurant_id":"41156888"},{$set:{"address.street":"Gang Senggol No. 7"}}) Update sub-field (array).
  3. db.restaurants.update({"address.zipcode":"10016",cuisine:"Other"},{$set:{cuisine:"Jajanan Pasar"},$currentDate:{"lastModified":true}},{multi:true}) Query diatas dilakukan untuk melakukan “Multi-Update”. Semua restaurant di zipcode 10016 dan yang Cuisinenya “Other” akan dirubah menjadi “jajanan Pasar”.
  4. db.restaurants.update({"restaurant_id":"30075445"},{"name":"Sari Sedap","address":{"coord":[-73.9557413,40.7720266],"building":"1480","street":"Gang Cinta","zipcode":"10075"}}) Query di atas melakukan “Replace”. Replace dilakukan dengan secara spesifik menyebutkan nilai field “_id” tanpa operator "$set". Jumlah Field-field yang baru tidak harus sama dengan field-field yang lama. Jika “restaurant_id” yang dimaksud tidak ada, maka tidak ada dokumen yang berubah/replaced.

Remove/Delete

  1. db.restaurants.remove({"name":"Sari Sedap"}) Query diatas menghapus “Semua” dokumen dimana field name-nya=”Sari Sedap”. Catatan: kalau dipikir-pikir, ada sedikit ke-tidak konsistenan di MongoDB. Coba lihat lagi Query No.1 di "Update". Jika logikanya sama (konsisten) seharunya yang terhapus hanya satu. Namun, ya … hati-hati saja … :D
  2. db.restaurants.remove( { "borough": "Queens" }, { justOne: true } ) Kalau mau delete cuma sebuah dokumen saja, maka tambahkan keterangan “JustOne:true” seperti query diatas.
  3. db.restaurants.remove({}) Perintah sakti untuk menghapus semua dokumen seperti “delete */Truncate” di database relasional.
  4. db.restaurants.drop() Menghapus sebuah koleksi di database MongoDB.

Aggregate/Group

  1. db.restaurants.aggregate([{$group:{"_id":"$cuisine","count":{$sum:1}}}]) Query diatas akan menghasilkan semua nilai field “Cuisine” yang berbeda dan jumlahnya (Ascending:1). Catatan: makna “_id” di query ini berbeda dengan “_id” yang automatis di buat oleh mongoDB. “_id” disini adalah id yang digunakan untuk menggroupkan Objek. Untuk lebih jelasnya, perhatikan query berikut.
  2. db.restaurants.aggregate([{$match:{"borough":"Queens","cuisine":"Italian"}},{$group:{"_id":"$address.zipcode","count":{$sum:1}}}]) Query tersebut menampilkan semua Zipcode (sebagai ID unik aggregatenya) dan jumlahnya (urut Asc) yang memenuhi predikat nilai field “Borough:Queens” DAN "cuisine:Italia".

INDEX

Collections di MongoDB memiliki minimal sebuah Index (i.e. _id), namun tentu saja kita bisa menambahkan index di fields yang lain. Index bagaikan katalog di perpustakaan. Ia digunakan untuk mempercepat pencarian, agar proses pencarian data tidak lagi harus dilakukan dengan traverse ke seluruh data di collection. Index di MongoDB sangat beragam. Mari kita bahas satu-persatu.
[1]. Index Biasa (Single Field):  db.restaurants.createIndex({"name":1})
Query tersebut menciptakan index di Field “Name” dan terurut menaik (Ascending). Index ini adalah index biasa seperti yang kita temukan di database relasional.
[2]. index Compound : db.restaurants.createIndex({"cuisine": 1,"address.zipcode":-1})
Index Compound adalah index yang dilakukan terhadap dua atau lebih fields secara sekaligus (multiple). Catatan: di single index urutan [1 atau –1] sebenarnya tidak terlalu berpengaruh (Karena MongoDB bisa traverse back & forth), namun di multiple (compound) index, urutan cukup berpengaruh. Untuk lebih jelasnya silahkan diperhatikan ilustrasi gambar compound index berikut (LINK).
[3]. Unique Index : db.restaurants.createIndex({"restaurant_id":1},{unique:true})
Index unique serupa dengan index unique di database relational. Apabila suatu field (e.g. restaurant_id) memiliki index unique, maka MongoDB akan menolak input dokumen baru dengan “restaurant_id” yang sama.
[4]. Sparse Index: db.restaurants.createIndex({website:1},{sparse:true})
Struktur data sparse biasa digunakan orang Data Mining (science) untuk menangani data dengan dimensi yang tinggi. Namun kali ini MongoDB dengan cukup apik, menyediakan fasilitas index sparse di databasenya. Index tipe ini menjadi penting untuk NoSQL, karena biasanya NoSQL schemaless, artinya tidak semua record (dokumen) memiliki suatu field tertentu. Dengan menggunakan index sparse, maka database (MongoDB) bisa jauh lebih efisien dengan meng-index hanya dokumen yang memiliki field tertentu (i.e. website dalam contoh ini).
[5]. Hashed Index: db.restaurants.createIndex({restaurant_id:"hashed"})
Jika belum terlalu lama berlalu-lalang di dunia database & kurang familiar tentang fungsi hash, keterangan tentang fungsi Hash dapat dibaca di LINK ini. Catatan: Hash Indexing di MongoDB disarankan di lakukan pada field yang besar, memiliki banyak nilai yang berbeda, dan monoton naik. Contohnya seperti “ID” atau “timestamps”. Catatan untuk para developer: tidak perlu untuk menghitung nilai Hash di aplikasi, MongoDB akan menghitungnya secara automatis, ketika query dilakukan pada field yang di index Hash.
[6]. 2DSphere index: db.restaurant_koord.createIndex({koordinat:"2dsphere"}) Ok, kalau anda jeli maka pertanyaan pertama kali adalah “kenapa restaurant_koord, bukan restaurants ???”. Ok sabar, sabar…. Pertama-tama mari kita bahas apa yang dimaksud dengan 2Dspehere index. Index ini digunakan untuk melakukan query berdasarkan proximity (kedekatan) lokasi. Salah satu feature unggul MongoDB yang sebenarnya juga sudah ada di search engine Sphinx. Bayangkan ketika menggunakan Google/Foursquare lalu user mencari objek (POI) terdekat dengan lokasi kita. Index ini melakukan hal tersebut. Mengapa restaurant_koord bukan restaurants ?  karena GeoLocation index (dan insert) hanya bisa dilakukan bila “semua” dokumen di koleksi memiliki informasi lokasi (latitude-longitude) dalam bentuk GeoJson (e.g. koordinat:[23.4,103.57]). Jika di koleksi ada dokumen yang tidak memiliki field tersebut maka indexing (atau input data) akan gagal. Catatan: Dari sudut pandang developer (database designer) sebaiknya dibuat 2 koleksi, satu untuk dokumen seperti biasa, dan yang kedua menyimpan “ID” dan lokasi. Dengan cara ini maka efisiensi dan performa database akan lebih terjaga. "Tapi restaurants punya informasi koordinat, mengapa tidap pakai itu saja ?" … Sayangnya tidak semua record di data latihan kita memiliki informasi koordinat, sehingga jika query diatas dilakukan di koleksi restaurants kita akan mendapatkan pesan error (silahkan di coba). Catatan: selain 2Dsphere, untuk Geolokasi MongoDB juga memiliki 2D index. GeoIndex juga bisa dibuat compound, sehingga pencarian seperti “Warung Padang near me” menjadi memungkinkan. Kembali ke Query indexing diatas, maka buatlah koleksi baru (i.e. restaurant_koord), lalu jalankan querynya setelah input contoh dua dokumen berikut: {loc:{type:"Point",koordinat:[-73.97,40.77]},name:"CentralPark",category:"Parks"} {loc:{type:"Point",koordinat:[-73.88,40.78]},name:"LaGuardiaAirport",category:"Airport"} Contoh Query geoLokasi: db.restaurant_koord.find({koordinat : {$near : [52,6]}}).limit(25) Catatan: Keywords "Limit" identik dengan Limit di database relasional dan bisa juga digunakan di query lain. [7]. Text Index: db.restaurants.createIndex({name:"text",cuisine:"text"}) Query di atas meng-index field text “name” dan “cuisine”. Catatan: Saya sangat tidak menyarankan index ini digunakan di “Production Level”. Untuk Text search dengan field yang panjang/besar seperti isi dokumen (skripsi,tesis,halaman web,dokumen perusahaan,dsb), sebaiknya menggunakan search engine khusus untuk Text seperti Solr, ElasticSearch, Sphinx, Lucene, atau semacamnya, lalu hubungkan (bridge) ke MongoDB (akan saya bahas di Post lain).

MongoDB Drivers & Summary

Salah satu hal penting dalam pemilihan sebuah database, adalah support driver. Sepertinya support driver MongoDB yang lengkap merupakan salah satu faktor pendukung mengapa MongoDB menjadi salah satu NoSQL paling populer saat ini. Setidaknya (minimal) terdapat driver support MongoDB untuk 13 bahasa pemrograman yang berbeda (C++, Java, PHP, Python, Erlang, Perl, dll). List lengkapnya ada di link berikut: LINK. Driver bahasa pemrograman lain, selain yang ada di list tersebut juga tersedia (e.g. Matlab atau actionscript) (LINK). Dukungan driver berarti komunitas yang besar, yang berarti juga support yang lebih baik.
Catatan: Seperti yang sudah disampaikan di awal post. Tentu saja “tidak ada gading yang tak retak”, tidak ada produk yang sempurna. Menurut pengalaman saya kelemahan driver MongoDB (& beberapa produk NoSQL lain) adalah perintah query yang berbeda dengan shell query di driver API-nya. Selain itu, tidak seperti driver database relasional yang memilki support penuh query seperti query di shell, di MongoDB, query yang bisa dijalankan lewat driver biasanya jauh lebih terbatas. Namun demikian, tentu saja beberapa query dasar yang penting seperti search, remove, update, dan indexing biasanya di support.

Summary-Kesimpulan

Pada post ini dijabarkan pendahuluan yang cukup lengkap tentang MongoDB, mulai dari instalasi, insert, query, indexing, dan driver. Kelebihan dan kelemahannya-pun ikut dibahas. Memahami kelebihan dan kekurangan suatu teknologi adalah hal terpenting dalam pengaplikasian yang optimal di level produksi. Seperti yang sudah pernah saya tuliskan sebelumnya, NoSQL seperti MongoDB bukanlah pengganti teknologi sebelumnya. Bukan juga suatu teknologi “full course” yang bisa digunakan untuk semua keperluan database (search engine). Kombinasi penggunaan beberapa teknologi database secara bersamaan telah menjadi solusi optimal di berbagai perusahaan besar. Optimasi yang dimaksud adalah optimal dari segi performa, biaya, dan keuntungan yang didapat.
Nantikan tulisan MongoDB lainnya tentang, Data Model Design, Sharding, Distributed system, Secondary Index, Replica, Analytic, Security, dll.

Tidak ada komentar:

Posting Komentar

Relevant & Respectful Comments Only.