Node dan label

Entitas, label ganda, dan konvensi penamaan node di Neo4j.

Daftar isi

Topik ini membahas node sebagai entitas dasar pada model property graph Neo4j beserta label yang menandai kelasnya. Lingkup pembahasannya mencakup label ganda pada satu node, konvensi penamaan label dan properti, serta kueri (query) MATCH yang dijangkarkan pada label dan kombinasinya. Seluruh contoh dijalankan langsung pada server Neo4j dengan data contoh perpustakaan berisi buku, anggota, dan penulis. Setelah membaca topik ini, entitas sederhana dapat dimodelkan sebagai node berlabel dan ditanyakan dengan kombinasi label yang tepat.

Node sebagai entitas#

Node adalah entitas diskrit yang disimpan sebagai simpul graf, misalnya satu buku, satu anggota, atau satu penulis. Berbeda dengan baris pada basis data relasional, node tidak terikat tabel maupun skema, dan atributnya berupa properti (property) yang melekat langsung pada node tersebut. Identitas node bersifat internal karena ditetapkan oleh Neo4j saat node dibuat, sehingga dua node dengan properti yang persis sama tetap merupakan dua entitas berbeda. Sebuah node diperbolehkan berdiri tanpa label sama sekali, tetapi pemodelan sehari-hari hampir selalu memberikan setidaknya satu label.

Data contoh pada topik ini berasal dari ranah perpustakaan dan seluruhnya fiktif, yaitu lima node :Buku, empat node :Anggota, dan tiga node :Penulis, ditambah satu penulis bernama Damar Wulung yang menjadi bahan pembahasan label ganda. Skrip penyiapan berikut ditulis dalam bahasa Cypher dan membangun data tersebut dengan MERGE, yaitu pola get-or-create yang mencocokkan node sebelum membuatnya, sehingga skrip bersifat idempoten dan dapat dijalankan berulang tanpa menimbulkan duplikasi. Pernyataan yang hanya menulis tidak mencetak baris keluaran apa pun di cypher-shell. Karena itu, blok penyiapan ditutup dengan kueri RETURN yang menampilkan isi :Buku sebagai konfirmasi.

cypher
MERGE (b:Buku {isbn: "978-0-00-000001-3"})
  SET b.judul = "Catatan Pengelana", b.tahunTerbit = 2019;
MERGE (b:Buku {isbn: "978-0-00-000002-0"})
  SET b.judul = "Rumah Pena", b.tahunTerbit = 2021;
MERGE (b:Buku {isbn: "978-0-00-000003-8"})
  SET b.judul = "Anak Muara", b.tahunTerbit = 2020;
MERGE (b:Buku {isbn: "978-0-00-000004-5"})
  SET b.judul = "Peta Angin", b.tahunTerbit = 2022;
MERGE (b:Buku {isbn: "978-0-00-000005-2"})
  SET b.judul = "Jejak Basirah", b.tahunTerbit = 2023;
MERGE (a:Anggota {nomorAnggota: 1}) SET a.nama = "Sari";
MERGE (a:Anggota {nomorAnggota: 2}) SET a.nama = "Tono";
MERGE (a:Anggota {nomorAnggota: 3}) SET a.nama = "Rina";
MERGE (a:Anggota {nomorAnggota: 4}) SET a.nama = "Wawan";
MERGE (p:Penulis {nama: "Nurul Widyastuti"});
MERGE (p:Penulis {nama: "Agam Prawira"});
MERGE (p:Penulis {nama: "Hana Fadhila"});
MERGE (p:Penulis {nama: "Damar Wulung"});
MATCH (b:Buku) RETURN b.judul AS judul, b.tahunTerbit AS tahunTerbit ORDER BY judul
text Keluaran
judul, tahunTerbit
"Anak Muara", 2020
"Catatan Pengelana", 2019
"Jejak Basirah", 2023
"Peta Angin", 2022
"Rumah Pena", 2021

Label ganda pada satu node#

Satu node dapat membawa lebih dari satu label sekaligus. Label menandai peran, sementara satu entitas nyata sering memainkan beberapa peran, misalnya anggota perpustakaan yang sekaligus penulis, atau pegawai yang terdaftar sebagai :Pegawai sekaligus :Anggota. Peran tambahan itu dinyatakan dengan label baru pada node yang sama, bukan dengan node kedua. Pada Neo4j, label baru ditambahkan melalui pernyataan SET dengan sintaks d:Anggota.

Node Damar Wulung dibuat oleh skrip penyiapan sebagai :Penulis. Pernyataan berikut menambahkan label :Anggota beserta properti nomorAnggota bernilai 5, kemudian menampilkan isi node tersebut setelah perubahan. Node yang sama kini membawa dua label, dan tidak ada node kedua yang dibuat.

cypher
MATCH (d:Penulis {nama: "Damar Wulung"})
SET d:Anggota, d.nomorAnggota = 5
RETURN d.nama AS nama, labels(d) AS label
text Keluaran
nama, label
"Damar Wulung", ["Penulis", "Anggota"]

Kedua label kini melekat pada satu node, sehingga pencarian pada salah satu label memasukkan node tersebut secara otomatis. Kueri berikut menampilkan seluruh node :Anggota bersama predikat label a:Penulis yang bernilai true atau false untuk setiap node. Predikat label inilah bentuk paling ringkas untuk menguji keanggotaan label pada data yang sudah tersimpan.

cypher
MATCH (a:Anggota) RETURN a.nama AS nama, a.nomorAnggota AS nomor, a:Penulis AS penulis ORDER BY nama
text Keluaran
nama, nomor, penulis
"Damar Wulung", 5, TRUE
"Rina", 3, FALSE
"Sari", 1, FALSE
"Tono", 2, FALSE
"Wawan", 4, FALSE

Damar Wulung tampil pada daftar anggota dengan nilai true pada kolom penulis, sedangkan keempat anggota lain bernilai false. Dari sisi :Penulis, node yang sama dijangkau oleh pola MATCH (p:Penulis) tanpa perlakuan khusus. Label ganda dengan demikian berfungsi sebagai dua saringan yang mengarah pada node yang sama.

Konvensi penamaan label dan properti#

Dokumentasi Neo4j merekomendasikan label ditulis dengan PascalCase, yaitu huruf kapital pada awal setiap kata tanpa pemisah, sehingga label pada data contoh ini ditulis :Buku, :Anggota, dan :Penulis. Properti mengikuti camelCase dengan huruf kecil pada kata pertama, seperti judul, tahunTerbit, isbn, dan nomorAnggota. Kedua gaya tersebut membedakan dua hal yang wujudnya berbeda, yaitu kelas tempat node terdaftar dan nilai yang melekat pada node.

Entitas grafGaya penamaanContoh
LabelPascalCase:Buku, :Anggota, :Penulis
ProperticamelCasejudul, tahunTerbit, isbn, nomorAnggota

Nama label dan properti bersifat sensitif huruf. Dokumentasi Neo4j menyebut :PERSON, :Person, dan :person sebagai tiga label yang berbeda. Kueri berikut mencari label :BUKU yang tidak pernah dibuat pada data contoh, padahal node :Buku sudah ada.

cypher
MATCH (b:BUKU) RETURN count(b) AS jumlahBuku
text Keluaran
jumlahBuku
0

Konsistensi penamaan menentukan kegunaan label dalam jangka panjang karena label menjadi pijakan kueri sekaligus indeks (index). Aturan baku lainnya ikut berlaku, yaitu nama diawali huruf alfabet, tidak memuat spasi, dan nama dengan karakter khusus diapit tanda kutip terbalik (backtick). Pemisah antarkata seperti garis bawah tidak digunakan pada label contoh ini agar gaya PascalCase tetap murni. Dengan konvensi yang konsisten, kekeliruan seperti :Buku dan :buku dapat dicegah sejak kueri pertama.

MATCH pada label dan kombinasi label#

Kueri MATCH dijangkarkan pada label, dan label itulah titik masuk pencarian yang paling murah. Pola MATCH (b:Buku) membatasi pencarian pada node berlabel :Buku saja, sebagaimana kueri penutup pada skrip penyiapan. Pola tanpa label seperti MATCH (n) memaksa Neo4j memeriksa setiap node graf, dan biayanya tumbuh seiring jumlah node.

Lebih dari satu label dapat dituliskan dalam satu pola. Bentuk dengan dua titik, :Anggota:Penulis, menuntut kedua label sekaligus sehingga cocok untuk mencari node berperan ganda. Bentuk dengan tanda pipa, :Buku|Penulis, menerima salah satu label saja. Semuanya termasuk label expression, yaitu ekspresi label yang dievaluasi pada setiap node, dan operator & serta ! menambahkan irisan dan negasi.

cypher
MATCH (n:Buku|Penulis) RETURN count(n) AS jumlahNode
text Keluaran
jumlahNode
9

Hasilnya sembilan, yaitu lima node :Buku ditambah empat node :Penulis. Damar Wulung terhitung satu kali meskipun membawa kedua label yang disebut dalam pola, sedangkan Sari, Tono, Rina, dan Wawan tidak terhitung karena tidak membawa label :Buku maupun :Penulis. Gabungan label dengan demikian tetap menghitung setiap node satu kali saja.

Negasi memperketat saringan dari arah yang berlawanan, yaitu mencari node yang membawa satu label tetapi tidak membawa label lain. Bentuk :Penulis&!Anggota digunakan untuk mencari penulis yang bukan anggota. Pola ini menghasilkan tiga penulis murni karena Damar Wulung tersaring keluar.

cypher
MATCH (n:Penulis&!Anggota) RETURN n.nama AS nama ORDER BY nama
text Keluaran
nama
"Agam Prawira"
"Hana Fadhila"
"Nurul Widyastuti"

Label juga menjadi tempat menempelnya indeks. Indeks dibuat untuk pasangan label dan properti tertentu, misalnya untuk (:Buku) pada properti judul, dan hanya kueri yang dijangkarkan pada label yang sama yang dapat memanfaatkannya. Karena itu label yang konsisten bukan sekadar kerapian, melainkan syarat agar indeks dapat bekerja. Mekanisme indeks beserta biaya dan cara mengukurnya menuntut pembahasan tersendiri dan tidak dicontohkan di topik ini.

Kesalahan umum#

Empat kesalahan berikut paling sering muncul saat topik ini dipraktikkan, beserta penyebab dan perbaikannya.

  1. Label ditulis dengan ejaan yang berbeda. Pencarian MATCH (b:BUKU) menghasilkan nol baris tanpa pesan error karena nama label sensitif huruf. Perbaikannya adalah mencocokkan ejaan dengan label yang sudah ada, misalnya dengan memeriksa daftar label pada basis data terlebih dahulu.
  2. Peran yang berbeda dibuatkan node terpisah. Penulis yang juga anggota kadang dimodelkan sebagai dua node, sehingga satu entitas terpecah dan relasinya menyebar ke dua tempat. Perbaikannya adalah satu node dengan label ganda, sebagaimana ilustrasi Damar Wulung.
  3. Pola MATCH ditulis tanpa label. Pola MATCH (n) memeriksa setiap node graf, dan biayanya tumbuh mengikuti ukuran data. Perbaikannya adalah mencantumkan label pada pola, karena label menjadi dasar indeks yang mempercepat pencarian properti.
  4. Label dianggap harus dideklarasikan lebih dahulu. Neo4j tidak mendaftarkan label ke skema, dan label baru tercipta otomatis saat node pertama diberi label tersebut. Perbaikannya adalah memberi label langsung melalui SET sambil menjaga konsistensi ejaan.

Ringkasan#

  • Node adalah entitas diskrit dengan identitas internal, dan propertinya melekat langsung pada node tanpa ikatan skema tabel.
  • Satu node dapat membawa beberapa label sekaligus, ditambahkan melalui SET dan diperiksa dengan labels() serta predikat label.
  • Label ditulis PascalCase dan properti ditulis camelCase, sedangkan ejaan yang berbeda menghasilkan label yang berbeda karena nama bersifat sensitif huruf.
  • Kueri MATCH dijangkarkan pada label, dapat mengombinasikan irisan, gabungan, dan negasi, serta menjadi dasar indeks per label.

Referensi#