Topik ini menetapkan batas keputusan antara basis data graf dan kandidat lain sebelum proyek rekomendasi pada modul ini dikerjakan. Pembahasannya mencakup dataset konsumsi kursus milik modul, kondisi yang membuat graf unggul, kondisi yang membuat kandidat lain lebih tepat, perbandingan per skenario, serta biaya operasional graf. Perbandingan diarahkan pada CTE rekursif PostgreSQL dan $lookup MongoDB yang mekanismenya telah dibahas pada modul Mengenal Neo4j, sehingga keduanya hanya menjadi pembanding keputusan. Setelah membacanya, pilihan teknologi untuk inti proyek rekomendasi dapat dinyatakan beserta alasannya.
Dataset konsumsi kursus modul ini#
Dataset modul ini memodelkan aktivitas belajar pada sebuah platform pembelajaran kursus. Enam pengguna disimpan sebagai node berlabel :Pengguna dengan properti nama, enam kursus disimpan sebagai node berlabel :Kursus dengan properti judul, dan relasi :MENGIKUTI berarah dari pengguna menuju kursus yang diikutinya. Setiap relasi membawa properti progres berupa bilangan bulat 0 sampai 100 yang menyatakan kemajuan belajar. Pola konsumsinya disusun agar bermakna, misalnya Hesti dan Kartika mengikuti tiga kursus yang sama, sedangkan pasangan lain berbagi satu atau dua kursus. Susunan tersebut meniru keadaan nyata platform pembelajaran, yaitu pengguna bertumpuk pada sebagian kursus dan berpisah pada sisanya.
Dataset dimuat dari berkas setup.cypher berikut yang idempoten (idempotent), sehingga pemuatan ulang tidak menggandakan data. Seluruh pernyataannya menggunakan MERGE dan MATCH yang telah dibahas pada modul Fundamental Cypher.
// Dataset contoh modul Pengerjaan proyek: rekomendasi, dipakai seluruh topik
// pada modul ini.
// Enam pengguna mengikuti enam kursus melalui relasi MENGIKUTI yang membawa
// properti progres berupa bilangan bulat 0-100.
// Skrip ini idempoten (idempotent), artinya aman dijalankan berulang kali.
// Node pengguna: label :Pengguna dengan properti nama.
MERGE (:Pengguna {nama: "Hesti"});
MERGE (:Pengguna {nama: "Indra"});
MERGE (:Pengguna {nama: "Joko"});
MERGE (:Pengguna {nama: "Kartika"});
MERGE (:Pengguna {nama: "Laila"});
MERGE (:Pengguna {nama: "Maya"});
// Node kursus: label :Kursus dengan properti judul.
MERGE (:Kursus {judul: "Pengantar Algoritma"});
MERGE (:Kursus {judul: "Basis Data Graf"});
MERGE (:Kursus {judul: "Statistika Terapan"});
MERGE (:Kursus {judul: "Pemrograman Python"});
MERGE (:Kursus {judul: "Jaringan Komputer"});
MERGE (:Kursus {judul: "Rekayasa Perangkat Lunak"});
// Relasi MENGIKUTI berarah dari pengguna menuju kursus, satu relasi per
// pasangan pengguna dan kursus, dengan properti progres.
MATCH (p:Pengguna {nama: "Hesti"}), (k:Kursus {judul: "Pengantar Algoritma"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 80;
MATCH (p:Pengguna {nama: "Hesti"}), (k:Kursus {judul: "Basis Data Graf"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 65;
MATCH (p:Pengguna {nama: "Hesti"}), (k:Kursus {judul: "Pemrograman Python"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 90;
MATCH (p:Pengguna {nama: "Hesti"}), (k:Kursus {judul: "Rekayasa Perangkat Lunak"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 40;
MATCH (p:Pengguna {nama: "Indra"}), (k:Kursus {judul: "Pengantar Algoritma"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 75;
MATCH (p:Pengguna {nama: "Indra"}), (k:Kursus {judul: "Pemrograman Python"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 60;
MATCH (p:Pengguna {nama: "Indra"}), (k:Kursus {judul: "Statistika Terapan"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 45;
MATCH (p:Pengguna {nama: "Joko"}), (k:Kursus {judul: "Basis Data Graf"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 55;
MATCH (p:Pengguna {nama: "Joko"}), (k:Kursus {judul: "Jaringan Komputer"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 70;
MATCH (p:Pengguna {nama: "Kartika"}), (k:Kursus {judul: "Pengantar Algoritma"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 70;
MATCH (p:Pengguna {nama: "Kartika"}), (k:Kursus {judul: "Basis Data Graf"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 60;
MATCH (p:Pengguna {nama: "Kartika"}), (k:Kursus {judul: "Pemrograman Python"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 85;
MATCH (p:Pengguna {nama: "Kartika"}), (k:Kursus {judul: "Jaringan Komputer"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 50;
MATCH (p:Pengguna {nama: "Laila"}), (k:Kursus {judul: "Statistika Terapan"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 80;
MATCH (p:Pengguna {nama: "Laila"}), (k:Kursus {judul: "Pemrograman Python"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 50;
MATCH (p:Pengguna {nama: "Laila"}), (k:Kursus {judul: "Jaringan Komputer"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 35;
MATCH (p:Pengguna {nama: "Maya"}), (k:Kursus {judul: "Basis Data Graf"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 90;
MATCH (p:Pengguna {nama: "Maya"}), (k:Kursus {judul: "Statistika Terapan"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 65;
MATCH (p:Pengguna {nama: "Maya"}), (k:Kursus {judul: "Rekayasa Perangkat Lunak"})
MERGE (p)-[r:MENGIKUTI]->(k)
SET r.progres = 30;# tidak-dijalankan
# memuat dataset contoh dari berkas setup.cypher ke dalam basis data
cat setup.cypher | cypher-shell -a bolt://127.0.0.1:7687 -u neo4jKelengkapan pemuatan diverifikasi dengan menghitung node pada roster yang didefinisikan oleh berkas setup.cypher, dan hasilnya menegaskan keenam pengguna dan keenam kursus tersedia.
MATCH (p:Pengguna)
WHERE p.nama IN ["Hesti", "Indra", "Joko", "Kartika", "Laila", "Maya"]
RETURN count(DISTINCT p.nama) AS jumlahPengguna;jumlahPengguna
6MATCH (k:Kursus)
WHERE k.judul IN ["Pengantar Algoritma", "Basis Data Graf", "Statistika Terapan", "Pemrograman Python", "Jaringan Komputer", "Rekayasa Perangkat Lunak"]
RETURN count(DISTINCT k.judul) AS jumlahKursus;jumlahKursus
6Kondisi yang membuat graf unggul#
Graf memberikan keunggulan nyata ketika karakter pertanyaannya memenuhi salah satu dari empat kondisi berikut. Pertama, kedalaman penelusuran tidak tetap atau baru diketahui pada saat kueri berjalan, sehingga jumlah lapisannya tidak dapat ditulis sejak awal. Kedua, relasi membawa fakta tersendiri seperti progres belajar pada relasi :MENGIKUTI, sehingga relasi berperan sebagai data dan bukan sekadar penghubung. Ketiga, jawaban yang diminta merupakan agregasi sepanjang jalur, misalnya banyaknya pengguna yang melintasi pola yang sama. Keempat, bentuk data terus berubah, misalnya jenis node dan relasi baru muncul tanpa merombak struktur yang sudah ada.
Kueri berikut mengilustrasikan kondisi tersebut pada dataset modul. Polanya menelusuri dua lompatan dari Hesti menuju kursus yang diikutinya, lalu menuju pengguna yang mengikuti kursus yang sama, dan berakhir pada kursus lain milik pengguna tersebut. Klausa WHERE menyaring kursus yang sudah diikuti Hesti, sedangkan DISTINCT menjaga setiap pasangan muncul satu kali.
MATCH (hesti:Pengguna {nama: "Hesti"})-[:MENGIKUTI]->(:Kursus)<-[:MENGIKUTI]-(sejawat)-[:MENGIKUTI]->(saran:Kursus)
WHERE NOT (hesti)-[:MENGIKUTI]->(saran)
RETURN DISTINCT sejawat.nama AS sejawat, saran.judul AS kursus_saran
ORDER BY sejawat, kursus_saran;sejawat, kursus_saran
"Indra", "Statistika Terapan"
"Joko", "Jaringan Komputer"
"Kartika", "Jaringan Komputer"
"Laila", "Jaringan Komputer"
"Laila", "Statistika Terapan"
"Maya", "Statistika Terapan"Enam baris keluaran dihasilkan oleh satu pola tanpa tabel keberhubungan yang dirakit secara manual. Setiap baris adalah jalur dua lompatan yang benar-benar dilintasi, sehingga biayanya sebanding dengan bagian graf yang disentuh. Apabila kebutuhan bergeser menjadi tiga lompatan, pola yang sama cukup diperpanjang satu ruas. Padanannya pada PostgreSQL adalah dua self join (penggabungan tabel dengan dirinya sendiri) untuk dua lapis, yang berubah menjadi CTE rekursif begitu kedalamannya tidak tetap, sedangkan pada MongoDB setiap lapisan menambah satu tahap $lookup. Cypher juga memungkinkan relasi membawa progres tanpa tabel perantara, sehingga faktor penilaian tersedia di sepanjang jalur yang dilintasi.
Kondisi yang membuat kandidat lain lebih tepat#
Kandidat pertama yang lebih tepat adalah mesin analitik untuk laporan agregat kaku. Rekapitulasi jumlah pengikut per kursus, rata-rata progres, dan statistik penyelesaian per bulan memiliki bentuk himpunan dan kolom yang stabil. Persoalan semacam ini adalah wilayah SQL dan paling murah dikerjakan pada penyimpan kolom (columnar) yang dirancang untuk pemrosesan analitis daring (online analytical processing, OLAP). Penelusuran graf menyentuh node per node, sedangkan mesin himpunan memindai baris secara massal, sehingga graf justru menjadi pilihan yang tidak efisien untuk laporan periodik.
Kandidat kedua adalah basis data dokumen untuk data yang lepas dari keberhubungan. Deskripsi panjang sebuah kursus, materi bacaan, dan halaman profil yang selalu dibaca utuh tidak menuntut penelusuran sama sekali. Menyimpannya sebagai dokumen mandiri menghilangkan biaya penelusuran yang tidak pernah dilakukan dan membebaskan graf dari node besar yang jarang tersambung.
Kandidat ketiga muncul ketika penelusurannya tetap dangkal dan volumenya besar. Apabila pertanyaannya selamanya dua lapis, dua join SQL yang terindeks menjawabnya dengan benar pada volume besar. Biaya mengoperasikan sistem tambahan jauh melebihi selisih performa antara keduanya, sehingga join yang cukup adalah keputusan yang lebih jujur. Graf baru memberikan manfaat apabila kedalaman pertanyaan bertambah atau bentuknya berubah.
Perbandingan per skenario#
Tabel berikut merangkum perbandingan tersebut per skenario. Pilihan yang tepat mengikuti karakter pertanyaan yang benar-benar dijalankan, bukan kesan umum bahwa data yang saling terhubung selalu milik graf. Setiap baris memasangkan satu skenario dengan satu pilihan teknologi, dan kolom alasan merujuk sifat mekanisme yang menentukannya.
| Skenario | Pilihan yang tepat | Alasan |
|---|---|---|
| Kedalaman lompatan tumbuh atau baru diketahui saat kueri berjalan | graf | pola lompatan diperpanjang tanpa menulis ulang kueri |
| Relasi membawa fakta seperti progres belajar | graf | relasi menyimpan properti sendiri sebagai data kelas satu |
| Laporan agregat periodik atas himpunan besar | SQL relasional atau penyimpan kolom | agregasi himpunan adalah wilayah aljabar relasional |
| Katalog dokumen yang selalu dibaca utuh | basis data dokumen | dokumen mandiri tidak menuntut penelusuran |
| Penelusuran tetap dua lapis pada volume besar | SQL relasional | dua join terindeks cukup tanpa menambah sistem baru |
| Laporan dan penelusuran sama-sama dominan | gabungan dua sistem | masing-masing mengerjakan pertanyaan yang paling pas |
Tabel tersebut menyederhanakan keputusan nyata yang biasanya mempertimbangkan ekosistem alat, kebiasaan tim, dan data yang sudah ada. Banyak sistem produksi menggunakan lebih dari satu model sekaligus, dan keputusan arsitektur yang baik menyebut pertanyaan mana yang diserahkan kepada sistem mana. Skenario pada tabel juga dapat bergeser seiring waktu, misalnya penelusuran yang semula tetap dua lapis tumbuh lebih dalam atau laporan agregat yang mulai mendominasi, sehingga keputusan perlu dinilai ulang setiap kali karakter pertanyaan utama berubah. Selain itu, kolom pilihan bukan pengganti pengukuran, karena biaya aktual setiap kandidat baru diketahui setelah kueri yang dominan diuji pada data nyata.
Biaya operasional graf#
Pilihan graf menambah satu kelas sistem yang harus dioperasikan. Server graf memiliki siklus pembaruan, pemantauan, dan cadangan (backup) tersendiri, sedangkan keterampilannya tidak otomatis sama dengan keterampilan SQL yang umum dimiliki tim. Ekosistem alat pendukungnya juga lebih kecil, misalnya pada penghubung untuk alat analitik dan pustaka pemetaan objek. Biaya tersebut wajar dibayar apabila pertanyaan penelusuran mendominasi, tetapi menjadi beban murni apabila kueri semacam itu jarang dijalankan.
Biaya yang sering diremehkan adalah alur sinkronisasi dari sistem sumber. Data operasional biasanya berasal dari basis data transaksional, sehingga salinannya pada graf harus disegarkan agar saran yang dihasilkan tetap mencerminkan keadaan terkini. Penyegaran yang tertinggal menghasilkan rekomendasi yang keliru, dan kondisi tersebut tidak terlihat dari grafnya sendiri karena datanya masih tersambung rapi.
Keputusan untuk proyek rekomendasi#
Proyek pada modul ini menempatkan kueri rekomendasi pada graf. Pertanyaan intinya adalah penelusuran konsumsi bersama yang kedalamannya tumbuh seiring perancangan, dari dua lompatan pada kueri paling sederhana menuju pembobotan progres dan lompatan yang lebih panjang apabila dibutuhkan. Relasi :MENGIKUTI yang membawa progres membuat faktor penilaian itu tersedia di sepanjang jalur tanpa penggabungan tambahan. Dataset konsumsi kursus yang diperkenalkan pada topik ini menjadi dasar seluruh kueri proyek, dan penempatan fakta pada relasinya mengikuti kaidah pemodelan yang dibahas pada modul Keputusan pemodelan.
Klaim yang menyertai keputusan tersebut tetap dibatasi. Kueri dua lompatan pada dataset sekecil ini juga dapat dijawab dua join SQL, sehingga pilihan graf tidak bertumpu pada volume data yang kecil. Graf dipilih karena bentuk pertanyaannya yang berubah dan biaya per jalurnya yang murah, sedangkan keputusan ini dinilai ulang apabila skenario bergeser menuju laporan agregat yang dominan. Penilaian kinerjanya dilakukan dengan indeks dan rencana kueri sebagaimana dibahas pada modul Performa.
Ringkasan#
- Graf unggul pada penelusuran yang kedalamannya tidak tetap, relasi yang membawa fakta sendiri, agregasi sepanjang jalur, dan data yang bentuknya terus berubah.
- Laporan agregat kaku tetap wilayah SQL dan penyimpan kolom, dokumen mandiri milik basis data dokumen, dan penelusuran dua lapis pada volume besar cukup dijawab dua join SQL.
- Graf menambah satu kelas sistem beserta biaya operasional dan alur sinkronisasinya, sehingga pilihannya merupakan keputusan arsitektur yang dinilai dari pertanyaan yang dijalankan.
- Proyek rekomendasi modul ini menempatkan kueri rekomendasi pada graf karena kedalaman penelusurannya tumbuh, sementara sumber kebenaran dan laporan agregat tetap pada sistem yang sudah ada.
Referensi#
- Introduction — Neo4j Docs — Pengantar Cypher beserta model property graph yang melandasi penelusuran relasi pada topik ini.
- WITH Queries (Common Table Expressions) — PostgreSQL Documentation — Semantik CTE rekursif PostgreSQL yang menjadi pembanding penelusuran kedalaman tidak tetap.
- $lookup (aggregation stage) — MongoDB Documentation
— Tahap agregasi
$lookupMongoDB yang menjadi pembanding penyusunan ulang hubungan antar dokumen.