Pola dalam MATCH

Sintaksis pola ala ASCII-art untuk membaca isi graf dengan MATCH.

Daftar isi

Cypher membaca isi graf dengan mencocokkan pola (pattern), yaitu gambaran bentuk node, relasi, dan properti yang ditulis menyerupai sketsa ASCII-art. Topik ini membahas klausa (clause) MATCH dari pola node paling sederhana sampai pola relasi berarah yang membentuk jalur dua lompatan. Setelah topik ini dibaca, kueri (query) pada graf contoh dapat ditulis dengan memilih label, properti jangkar, dan arah relasi yang tepat.

Dataset contoh#

Seluruh contoh pada topik ini menggunakan dataset jaringan sosial kecil yang sama, yaitu empat orang bernama Ali, Budi, Citra, dan Dewi, serta empat kota bernama Jakarta, Bandung, Surabaya, dan Medan. Setiap orang disimpan sebagai node berlabel :Person dengan properti name dan tahunLahir, sedangkan setiap kota disimpan sebagai node berlabel :Kota dengan properti name. Relasi :KENAL menghubungkan dua orang dan menyimpan tanggal perkenalan pada properti sejak, sedangkan relasi :DOMISILI menghubungkan orang dengan kota tempat tinggalnya. Diagram berikut menampilkan bentuk graf tersebut, termasuk lima relasi KENAL dan empat relasi DOMISILI di dalamnya.

KENALDOMISILIKENALKENALKENALKENALKENALDOMISILIDOMISILIDOMISILIDOMISILIAliBudiCitraDewiJakartaMedanBandungSurabayabelum ada penghuni
Dataset contoh: empat orang, empat kota, serta relasi KENAL dan DOMISILI

Dataset dimuat dari berkas setup.cypher berikut. Skripnya idempoten (idempotent), artinya aman dijalankan berulang kali karena node dan relasi yang sudah ada tidak dibuat ulang. Sintaks di dalamnya dibahas pada topik membuat dan mengubah data, sehingga berkas ini cukup dijalankan apa adanya.

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);

Muat berkas tersebut ke dalam Neo4j melalui cypher-shell dengan perintah berikut.

bash
# tidak-dijalankan
# memuat dataset contoh dari berkas setup.cypher ke dalam basis data
cat setup.cypher | cypher-shell -u neo4j

Anatomi pola node dan relasi#

Kueri Cypher menyerupai gambar yang dianotasi dengan teks. Pola node ditulis di dalam tanda kurung, misalnya (p:Person), yang berarti sebuah node dengan variabel p dan label Person. Pola relasi ditulis di dalam tanda kurung siku dengan panah, misalnya -[:KENAL]->, yang menggambar sebuah panah dari satu node menuju node lain. Klausa MATCH mencari setiap subgraf yang bentuknya sesuai dengan pola tersebut, lalu klausa RETURN menentukan nilai yang ditampilkan pada setiap baris hasil. Kueri berikut mengambil semua orang beserta tahun lahirnya.

cypher
MATCH (p:Person)
RETURN p.name AS nama, p.tahunLahir AS lahir
ORDER BY nama;
text Keluaran
nama, lahir
"Ali", 1990
"Budi", 1988
"Citra", 1992
"Dewi", 1985

Keluaran menampilkan empat baris karena graf contoh memuat empat node :Person. Bagian ORDER BY nama mengunci urutan baris menurut abjad agar contoh pada topik ini mudah dibandingkan, dan rincian pengurutannya dibahas pada topik menyaring dan membentuk hasil. Pola juga boleh merentang dua node sekaligus, sebagaimana kueri berikut yang menghubungkan orang dengan kota domisilinya.

cypher
MATCH (p:Person)-[:DOMISILI]->(k:Kota)
RETURN p.name AS nama, k.name AS kota
ORDER BY nama;
text Keluaran
nama, kota
"Ali", "Jakarta"
"Budi", "Bandung"
"Citra", "Bandung"
"Dewi", "Medan"

Pola (p:Person)-[:DOMISILI]->(k:Kota) terbaca sebagai kalimat: sebuah orang memiliki relasi DOMISILI menuju sebuah kota. Tanda panah menunjukkan arah relasi sebagaimana relasi itu tersimpan, dan bentuknya memang menggambar graf itu sendiri, sehingga pola panjang sekalipun tetap terbaca tanpa penjelasan tambahan.

Menjangkar pola pada node tertentu#

Tanpa jangkar, MATCH (p:Person) mengembalikan semua orang di dalam graf. Kueri menjadi lebih terarah apabila pola memuat syarat properti di dalam kurung kurawal, misalnya {name: "Ali"}, yang hanya cocok dengan node berproperti tersebut. Jangkar semacam ini berlaku seperti alamat node yang dicari, dan sisanya pola cukup menggambar relasinya.

cypher
MATCH (p:Person {name: "Ali"})
RETURN p;
text Keluaran
p
(:Person {name: "Ali", tahunLahir: 1990})

Keluaran menampilkan satu node utuh beserta label dan propertinya. Jangkar properti biasanya dirangkai dengan pemilihan nilai tertentu pada RETURN, sebagaimana kueri berikut yang mengambil orang yang dikenali Ali beserta tanggal perkenalannya.

cypher
MATCH (:Person {name: "Ali"})-[r:KENAL]->(teman)
RETURN teman.name AS dikenal, r.sejak AS sejak
ORDER BY dikenal;
text Keluaran
dikenal, sejak
"Budi", 2019-03-10
"Citra", 2021-01-15

Cara Cypher mengeksekusi sebuah pola dapat diamati dengan mengawali kueri menggunakan kata PROFILE, dan rencana eksekusinya dibahas lebih rinci pada modul performa. Untuk graf kecil seperti dataset contoh, pilihan jangkar belum terasa, sedangkan pada graf besar jangkar yang tepat menentukan kecepatan kueri.

Arah dan tipe relasi#

Tipe relasi di dalam kurung siku membatasi pola pada satu jenis hubungan, dan panah menentukan arahnya. Pola -[:KENAL]-> hanya cocok dengan relasi yang tersimpan mengarah keluar dari node pertama, sedangkan pola -[:KENAL]- tanpa panah mencocokkan relasi tersebut dari kedua arah. Pencarian dua arah tidak berarti relasinya tersimpan ganda, melainkan Neo4j menelusuri relasi yang sama ke arah bolak-balik. Kueri berikut mengambil semua orang yang terhubung relasi KENAL dengan Citra, tidak peduli siapa yang mengenali siapa lebih dahulu.

cypher
MATCH (:Person {name: "Citra"})-[:KENAL]-(lain)
RETURN lain.name AS terhubung
ORDER BY terhubung;
text Keluaran
terhubung
"Ali"
"Budi"
"Dewi"

Keluaran memuat tiga nama karena Citra dikenali oleh Ali dan Budi, sedangkan Citra mengenali Dewi. Pola berarah dan pola dua arah sama-sama menggambar relasi yang tersimpan, sehingga pilihan arah ditentukan oleh pertanyaan yang diajukan, bukan oleh cara data disimpan.

Pola majemuk dan jalur dua lompatan#

Pola boleh dirangkai menjadi jalur panjang dengan menggantikan node tengahnya. Node yang tidak perlu dirujuk lagi ditulis tanpa variabel dalam tanda kurung kosong (), sedangkan node ujung yang hasilnya ingin ditampilkan diberi variabel. Kueri berikut mencari orang yang dicapai dari Ali melalui dua relasi KENAL berturut-turut.

cypher
MATCH (:Person {name: "Ali"})-[:KENAL]->()-[:KENAL]->(jauh)
RETURN jauh.name AS dua_lompatan
ORDER BY dua_lompatan;
text Keluaran
dua_lompatan
"Citra"
"Dewi"

Hasilnya adalah Citra, yang dicapai melalui Budi, dan Dewi, yang dicapai melalui Citra. Rangkaian pola semacam ini tetap satu klausa MATCH, sehingga seluruh jalurnya wajib cocok sekaligus agar baris hasil muncul. Penulisan jalur yang panjangnya bebas dibahas pada modul pola kueri, sedangkan pola tetap seperti ini cukup untuk mayoritas kueri pembacaan.

Kesalahan umum#

  1. Pola node tanpa label. Pola MATCH (p) cocok dengan setiap node di dalam graf, baik orang, kota, maupun label lain yang mungkin ada, sehingga keluarannya memuat baris yang tidak diharapkan dan pemindaiannya menjadi mahal. Cantumkan label pada setiap pola, misalnya MATCH (p:Person).
  2. Variabel yang sama untuk dua posisi node. Pola (a)-[:KENAL]->(a) menggunakan satu variabel untuk dua posisi, dan satu variabel selalu berarti node yang sama, sehingga pola itu hanya cocok dengan orang yang mengenal dirinya sendiri. Keluarannya kosong pada dataset contoh, dan perbaikannya adalah menggunakan variabel berbeda seperti (a)-[:KENAL]->(b).
  3. Arah panah yang terbalik. Pola (:Person {name: "Ali"})<-[:KENAL]-(teman) mengembalikan orang yang mengenali Ali, yaitu Dewi, bukan orang yang dikenali Ali. Periksa arah relasi pada model data terlebih dahulu, lalu tulis panah menurut arah tersimpannya.

Ringkasan#

  • MATCH mencari setiap subgraf yang sesuai pola, dan pola ditulis menyerupai sketsa graf, misalnya (p:Person {name: "Ali"})-[:KENAL]->(teman).
  • Label dan syarat properti bertindak sebagai jangkar yang mempersempit hasil sekaligus menjadi titik awal penelusuran planner.
  • Relasi ditulis berarah -[]-> atau dua arah -[]-, sedangkan relasi tetap tersimpan searah dan penelusuran dua arah dilakukan saat kueri berjalan.
  • Pola dirangkai menjadi jalur berlompatan, dan node tengah yang tidak dirujuk ditulis anonim sebagai ().

Referensi#