Membuat dan mengubah data

CREATE, SET, REMOVE, DELETE, dan DETACH DELETE untuk mengelola isi graf.

Daftar isi

Klausa CREATE, SET, REMOVE, DELETE, dan DETACH DELETE menuliskan isi graf: menambahkan node dan relasi baru, mengubah properti serta label, dan menghapus data yang tidak lagi diperlukan. Topik ini membahas kelima klausa tersebut di atas dataset jaringan sosial modul ini beserta keluaran aslinya. Setelah dibaca, perubahan data dapat dilakukan dengan pola yang tepat sasarannya dan risiko penghapusannya terkendali.

Dataset contoh#

Dataset contoh modul ini adalah jaringan sosial kecil yang berisi empat orang bernama Ali, Budi, Citra, dan Dewi, serta empat kota bernama Jakarta, Bandung, Surabaya, dan Medan. Relasi :KENAL menghubungkan dua orang dan menyimpan tanggal perkenalan pada properti sejak, sedangkan relasi :DOMISILI menghubungkan orang dengan kota tempat tinggalnya. Kota Surabaya digunakan sebagai sasaran contoh karena belum memiliki relasi DOMISILI dari orang mana pun pada data awal. Seluruh contoh pada topik ini bergerak di atas dataset tersebut sebagai titik awal.

Data awal dimuat dari berkas setup.cypher berikut. Skripnya idempoten (idempotent), artinya aman dijalankan berulang kali karena node dan relasi yang sudah ada tidak dibuat ulang. Contoh pada topik ini juga menambahkan node sementara bernama Sasih dan Pandu beserta dua node :Catatan, kemudian menghapus semuanya pada bagian akhir, sehingga graf kembali berada pada keadaan semula. Penghapusan pada topik ini hanya menyasar node-node sementara tersebut, sehingga data awal empat orang dan empat kota tidak pernah berubah.

cypher setup.cypher
// Dataset contoh modul Fundamental Cypher: jaringan sosial kecil
// dengan empat orang dan empat kota.
// Skrip ini idempoten (idempotent), artinya aman dijalankan berulang kali.

// Node orang: label :Person dengan properti name dan tahunLahir.
MERGE (ali:Person {name: "Ali"})
  SET ali.tahunLahir = 1990;
MERGE (budi:Person {name: "Budi"})
  SET budi.tahunLahir = 1988;
MERGE (citra:Person {name: "Citra"})
  SET citra.tahunLahir = 1992;
MERGE (dewi:Person {name: "Dewi"})
  SET dewi.tahunLahir = 1985;

// Node kota: label :Kota dengan properti name.
MERGE (jakarta:Kota {name: "Jakarta"});
MERGE (bandung:Kota {name: "Bandung"});
MERGE (surabaya:Kota {name: "Surabaya"});
MERGE (medan:Kota {name: "Medan"});

// Relasi KENAL berarah antar orang, dengan properti sejak.
MATCH (ali:Person {name: "Ali"}), (budi:Person {name: "Budi"})
  MERGE (ali)-[r:KENAL]->(budi)
  SET r.sejak = date("2019-03-10");
MATCH (ali:Person {name: "Ali"}), (citra:Person {name: "Citra"})
  MERGE (ali)-[r:KENAL]->(citra)
  SET r.sejak = date("2021-01-15");
MATCH (budi:Person {name: "Budi"}), (citra:Person {name: "Citra"})
  MERGE (budi)-[r:KENAL]->(citra)
  SET r.sejak = date("2020-07-21");
MATCH (citra:Person {name: "Citra"}), (dewi:Person {name: "Dewi"})
  MERGE (citra)-[r:KENAL]->(dewi)
  SET r.sejak = date("2018-11-05");
MATCH (dewi:Person {name: "Dewi"}), (ali:Person {name: "Ali"})
  MERGE (dewi)-[r:KENAL]->(ali)
  SET r.sejak = date("2017-06-02");

// Relasi DOMISILI dari orang menuju kota tempat tinggalnya.
MATCH (ali:Person {name: "Ali"}), (jakarta:Kota {name: "Jakarta"})
  MERGE (ali)-[:DOMISILI]->(jakarta);
MATCH (budi:Person {name: "Budi"}), (bandung:Kota {name: "Bandung"})
  MERGE (budi)-[:DOMISILI]->(bandung);
MATCH (citra:Person {name: "Citra"}), (bandung:Kota {name: "Bandung"})
  MERGE (citra)-[:DOMISILI]->(bandung);
MATCH (dewi:Person {name: "Dewi"}), (medan:Kota {name: "Medan"})
  MERGE (dewi)-[:DOMISILI]->(medan);
bash
# tidak-dijalankan
# memuat dataset contoh dari berkas setup.cypher ke dalam basis data
cat setup.cypher | cypher-shell -u neo4j

Membuat node dengan CREATE#

Klausa CREATE selalu menambahkan entitas baru tanpa memeriksa keberadaan entitas serupa terlebih dahulu. Pola node ditulis di dalam tanda kurung beserta propertinya di dalam kurung kurawal, sebagaimana pola pada MATCH. Variabel pada node yang dibuat bersifat opsional dan hanya diperlukan apabila node itu dirujuk oleh klausa berikutnya. Kueri berikut membuat satu node :Person baru bernama Sasih, lalu menampilkan isinya melalui RETURN.

cypher
CREATE (s:Person {name: "Sasih", tahunLahir: 1994})
RETURN s.name AS nama, s.tahunLahir AS lahir;
text Keluaran
nama, lahir
"Sasih", 1994

Satu pernyataan CREATE boleh memuat beberapa pola yang dipisahkan tanda koma, sehingga beberapa node dibuat sekaligus dalam satu langkah. Variabel c1 dan c2 diperlukan karena nilai keduanya ditampilkan pada RETURN yang sama. Kueri berikut membuat dua node :Catatan dan mengembalikan isi keduanya pada satu baris hasil.

cypher
CREATE (c1:Catatan {isi: "belanja mingguan"}),
       (c2:Catatan {isi: "jadwal piket"})
RETURN c1.isi AS pertama, c2.isi AS kedua;
text Keluaran
pertama, kedua
"belanja mingguan", "jadwal piket"

Membuat relasi dengan CREATE#

Relasi dibuat dengan pola panah yang menghubungkan dua variabel node, misalnya (s)-[:DOMISILI]->(k). Apabila kedua node ujung sudah ada, keduanya diikat lebih dahulu dengan MATCH, lalu CREATE menggambar relasinya. Pemisahan ini penting karena node yang ditulis langsung di dalam CREATE selalu dibuat baru, bukan dicari. Satu pernyataan CREATE juga boleh memuat beberapa pola relasi sekaligus, sebagaimana kueri berikut yang menambahkan dua relasi bagi Sasih dalam satu langkah, yaitu domisili di Surabaya dan perkenalan dengan Citra.

cypher
MATCH (s:Person {name: "Sasih"}), (k:Kota {name: "Surabaya"}), (c:Person {name: "Citra"})
CREATE (s)-[:DOMISILI]->(k), (s)-[:KENAL {sejak: date("2025-01-20")}]->(c)
RETURN s.name AS sasih, k.name AS domisili, c.name AS dikenal;
text Keluaran
sasih, domisili, dikenal
"Sasih", "Surabaya", "Citra"

Pola node dan pola relasi juga boleh digabungkan dalam satu CREATE, sehingga node baru langsung terbentuk bersama relasinya. Kueri berikut membuat node bernama Pandu yang langsung terhubung relasi KENAL menuju Dewi. Node Dewi diikat MATCH lebih dahulu, sebab penulisannya langsung di dalam CREATE akan membuat node Dewi kedua alih-alih menggunakan node yang sudah ada. Properti sejak pada relasi baru dituliskan sebagaimana properti pada node.

cypher
MATCH (d:Person {name: "Dewi"})
CREATE (p:Person {name: "Pandu", tahunLahir: 1987})-[:KENAL {sejak: date("2025-02-14")}]->(d)
RETURN p.name AS node_baru, d.name AS dikenal;
text Keluaran
node_baru, dikenal
"Pandu", "Dewi"

Mengubah nilai dengan SET#

Klausa SET mengubah properti pada node atau relasi yang terikat variabel. Nilai yang sudah ada ditimpa tanpa peringatan, sedangkan properti yang belum ada langsung ditambahkan. Kueri berikut mengganti tahun lahir Sasih yang semula 1994 menjadi 1995.

cypher
MATCH (s:Person {name: "Sasih"})
SET s.tahunLahir = 1995
RETURN s.name AS nama, s.tahunLahir AS lahir;
text Keluaran
nama, lahir
"Sasih", 1995

Operator += menggabungkan sebuah peta (map) ke dalam properti node. Kunci yang sudah ada ditimpa nilainya, kunci yang belum ada ditambahkan, sedangkan properti lain di luar peta tetap utuh. Perilaku itu berbeda dengan operator = yang menggantikan seluruh properti node dengan isi petanya. Kueri berikut menambahkan dua properti baru pada node Sasih melalui peta.

cypher
MATCH (s:Person {name: "Sasih"})
SET s += {kotaAsal: "Medan", pekerjaan: "analis data"}
RETURN s.kotaAsal AS asal, s.pekerjaan AS pekerjaan;
text Keluaran
asal, pekerjaan
"Medan", "analis data"

SET juga menambahkan label dengan menuliskan tanda titik dua beserta nama labelnya di belakang variabel. Sebuah node boleh memiliki beberapa label sekaligus, dan label baru tidak mengganggu label yang sudah tersimpan. Kueri berikut menambahkan label :Pegawai pada node Sasih di samping label Person yang sudah ada, sedangkan fungsi labels() mengembalikan seluruh label node sebagai daftar.

cypher
MATCH (s:Person {name: "Sasih"})
SET s:Pegawai
RETURN labels(s) AS label;
text Keluaran
label
["Person", "Pegawai"]

Menghapus properti dan label dengan REMOVE#

Klausa REMOVE mencabut properti atau label dari node yang terikat variabel, sedangkan penghapusan entitas utuh adalah tugas DELETE. Properti yang sudah dicabut tidak lagi tersimpan, dan pembacaannya menghasilkan null yang oleh cypher-shell ditampilkan sebagai NULL. Menetapkan null melalui SET memberikan efek yang sama, sehingga pencabutan properti dapat dilakukan dari salah satu klausa. Klausa ini juga berlaku pada properti relasi, misalnya REMOVE r.sejak pada relasi yang terikat variabel. Kueri berikut mencabut properti pekerjaan dari node Sasih, sedangkan properti kotaAsal tetap tersimpan.

cypher
MATCH (s:Person {name: "Sasih"})
REMOVE s.pekerjaan
RETURN s.kotaAsal AS asal, s.pekerjaan AS pekerjaan;
text Keluaran
asal, pekerjaan
"Medan", NULL

Label dicabut dengan sintaks yang sama beserta tanda titik duanya. Penghapusan label tidak mengubah properti maupun relasi node, sehingga node itu tetap utuh sebagai Person beserta kedua relasinya. Perubahan semacam ini bersifat lokal pada node yang dicocokkan, sehingga data node lain tidak terpengaruh. Kueri berikut mencabut label :Pegawai yang sebelumnya ditambahkan, dan node Sasih kembali hanya berlabel Person.

cypher
MATCH (s:Person {name: "Sasih"})
REMOVE s:Pegawai
RETURN labels(s) AS label;
text Keluaran
label
["Person"]

Menghapus data dengan DELETE dan DETACH DELETE#

Klausa DELETE menghapus relasi atau node dari graf. Node yang masih memiliki relasi menolak untuk dihapus, karena penghapusan itu akan membiarkan relasi menggantung tanpa salah satu ujungnya. Kueri berikut mencoba menghapus node Sasih yang masih memiliki dua relasi, yaitu KENAL menuju Citra dan DOMISILI menuju Surabaya. cypher-shell menampilkan pesan error, dan tidak ada satu pun data yang berubah.

cypher
MATCH (s:Person {name: "Sasih"})
DELETE s;
text Keluaran
G1001: dependent object error - edges still exist

Pesan error tersebut menyatakan bahwa relasi node masih ada (edges still exist), sehingga relasi Sasih wajib dihapus lebih dahulu. Pola -[r]-() tanpa panah mencocokkan relasi dari kedua arah, sehingga relasi keluar dan masuk terhapus sekaligus. Fungsi count() pada RETURN yang sama masih membaca entitas yang baru dihapus, sehingga jumlah penghapusannya dapat ditampilkan.

cypher
MATCH (:Person {name: "Sasih"})-[r]-()
DELETE r
RETURN count(r) AS relasi_dihapus;
text Keluaran
relasi_dihapus
2

Node yang sudah tidak memiliki relasi dihapus seperti node lainnya. Kueri berikut menghapus node Sasih dan menampilkan jumlah node yang terhapus.

cypher
MATCH (s:Person {name: "Sasih"})
DELETE s
RETURN count(*) AS node_dihapus;
text Keluaran
node_dihapus
1

Node yang tidak memiliki relasi sama sekali boleh langsung dihapus tanpa langkah persiapan. Kueri berikut menghapus kedua node :Catatan yang dibuat pada bagian awal.

cypher
MATCH (c:Catatan)
DELETE c
RETURN count(*) AS node_dihapus;
text Keluaran
node_dihapus
2

Klausa DETACH DELETE memadatkan dua langkah sebelumnya menjadi satu. Node yang dicocokkan dihapus beserta seluruh relasinya, baik yang mengarah keluar maupun masuk, sedangkan node ujung relasi tetap tersimpan. Kueri berikut menghapus Pandu beserta satu relasi KENAL miliknya, dan node Dewi tetap ada di dalam graf.

cypher
MATCH (p:Person {name: "Pandu"})
DETACH DELETE p
RETURN count(*) AS node_dihapus;
text Keluaran
node_dihapus
1

Kesalahan umum#

  1. Pola DELETE tanpa penyaring. Pola MATCH (n) DELETE n mencocokkan setiap node tanpa kecuali, sehingga seluruh isi basis data terhapus dan tidak dapat dikembalikan. Tambahkan label pada pola dan syarat WHERE, kemudian uji pola itu dengan RETURN count(*) sebelum kata DELETE digunakan.
  2. Menghapus node yang masih memiliki relasi. DELETE menolak bekerja dan menampilkan error G1001, sehingga pernyataan tidak memberikan efek apa pun. Hapus relasinya terlebih dahulu, atau gunakan DETACH DELETE apabila relasi tersebut memang ikut dibuang.
  3. Menjalankan ulang CREATE. Pernyataan CREATE selalu membuat entitas baru, sehingga skrip penyiapan yang dijalankan dua kali menggandakan node dan relasinya. Skrip data awal sebaiknya menggunakan MERGE yang mencari pola lebih dahulu sebelum membuatnya.
  4. Menukar operator = dengan += pada SET. Bentuk SET s = {...} menggantikan seluruh properti node dan membuang properti lain yang tidak disebutkan, sedangkan SET s += {...} hanya menimpa kunci yang ada di dalam petanya. Gunakan += untuk menambah atau memperbarui sebagian properti.

Ringkasan#

  • CREATE menambahkan node dan relasi baru tanpa memeriksa keberadaan, dan satu pernyataan boleh memuat beberapa pola sekaligus.
  • SET mengubah nilai properti, menambahkan label, serta menggabungkan peta melalui +=, sedangkan REMOVE mencabut properti dan label.
  • DELETE menghapus relasi atau node tanpa relasi, sedangkan DETACH DELETE menghapus node beserta seluruh relasinya dalam satu langkah.
  • Pola penghapusan wajib dibatasi label dan WHERE, dan sasarannya dihitung terlebih dahulu dengan RETURN count(*).

Referensi#