Database

Neo4j: Graph Database — Cypher, Nodes, Relationships & Patterns

Pelajari Neo4j dan bahasa query Cypher untuk membangun graph database — dari konsep dasar nodes dan relationships hingga pattern matching dan algoritma graph

1. Pengenalan Graph Database & Neo4j

Graph Database adalah database yang menyimpan data dalam bentuk graph — jaringan node (titik) dan relationship (garis penghubung). Berbeda dari database relasional yang menyimpan data dalam tabel, graph database fokus pada hubungan antar data.

Neo4j adalah graph database paling populer di dunia. Dibangun sejak 2007, Neo4j menggunakan model Labeled Property Graph dan bahasa query Cypher yang intuitif dan ekspresif.

Diagram: Relasional vs Graph Database
┌─────────────────────────────────────────────────────────────────┐
│           RELATIONAL DATABASE           GRAPH DATABASE          │
│                                                                 │
│  ┌──────────┐  ┌──────────┐         (Person)                   │
│  │ Person   │  │ Friend   │          ●──────●                   │
│  ├──────────┤  ├──────────┤         /│      │\                  │
│  │ id       │  │ person_id│        ● │      │ ●                │
│  │ name     │  │ friend_id│         \│      │/                  │
│  │ age      │  │ since    │          ●──────●                   │
│  └──────────┘  └──────────┘                                      │
│                                                                 │
│  SELECT p.name, f.name           MATCH (p:Person)-[:FRIEND]->   │
│  FROM person p                     (f:Person)                    │
│  JOIN friend fr                    RETURN p.name, f.name         │
│    ON p.id = fr.person_id                                       │
│  JOIN person f                                                  │
│    ON f.id = fr.friend_id        Lebih intuitif & cepat          │
│  WHERE p.name = 'Budi';           untuk query hubungan!          │
│                                                                 │
│  3 tabel JOIN untuk teman        1 pattern cukup                 │
└─────────────────────────────────────────────────────────────────┘

Kapan Menggunakan Graph Database?

Use Case Mengapa Graph? Contoh
Social NetworkHubungan antar user sangat kompleksFacebook, LinkedIn
Recommendation Engine"Orang yang beli X juga beli Y"Amazon, Netflix
Fraud DetectionTemukan pola transaksi mencurigakanBank, payment gateway
Knowledge GraphHubungan antar entitas dan konsepGoogle Knowledge Graph
Network/IT InfrastructureTopologi jaringan dan dependenciesCloud monitoring
Route PlanningShortest path antar lokasiGoogle Maps, GPS

Setup Neo4j

Bash — Instalasi Neo4j
# ===== Docker (rekomendasi untuk development) =====
docker run \
    --name neo4j \
    -p 7474:7474 -p 7687:7687 \
    -e NEO4J_AUTH=neo4j/password123 \
    -e NEO4J_PLUGINS='["apoc"]' \
    neo4j:5-community

# Browser: http://localhost:7474
# Bolt protocol: bolt://localhost:7687

# ===== Download langsung =====
# https://neo4j.com/download/
# Community Edition (gratis) sudah cukup untuk belajar

# ===== Neo4j Aura (Cloud, Free Tier) =====
# https://neo4j.com/cloud/aura-free/
# Managed service, tidak perlu instalasi

2. Nodes, Relationships & Properties

Konsep Dasar Property Graph

Komponen Simbol Cypher Penjelasan
Node(n:Label)Entitas (orang, produk, tempat) — punya label dan properties
Relationship-[r:TYPE]->Hubungan antar node — selalu punya arah dan tipe
Label:PersonKategori/tipe node — bisa punya banyak label
Property{name: 'Budi'}Data key-value pada node atau relationship
Diagram: Property Graph Model
┌─────────────────────────────────────────────────────────────────┐
│                   PROPERTY GRAPH MODEL                           │
│                                                                 │
│         {name: 'Budi'}           {name: 'Sari'}                │
│        ●──────────────●───────────────●                         │
│       /│  :Person     │               │\                        │
│      / │              │               │ \                       │
│     /  │    :KNOWS    │               │  \                      │
│    /   │   {since:    │               │   \                     │
│   /    │    2020}     │               │    \                    │
│  ●     │              │               │     ●                   │
│ {name: │              │               │  {name:                 │
│ 'Rina'}│              │               │  'Andi'}                │
│ :Person│              │               │  :Person                │
│        │              │               │                         │
│        ●──────────────┘               └──────────●              │
│         :WORKS_AT                             :WORKS_AT         │
│         {role: 'Engineer'}                    {role: 'PM'}      │
│                  │                                         │     │
│         ●────────┘                                         │     │
│        {name: 'TechCorp'}           ●──────────────────────┘     │
│        :Company                  {name: 'StartupXYZ'}           │
│                                  :Company                        │
│                                                                 │
│  Node punya: Label + Properties (key-value)                     │
│  Relationship punya: Tipe + Arah + Properties                   │
└─────────────────────────────────────────────────────────────────┘
Cypher — Membuat Nodes & Relationships
// =============================================
// MEMBUAT NODES
// =============================================

// Buat node Person dengan properties
CREATE (budi:Person {
    name: 'Budi Santoso',
    age: 28,
    email: 'budi@email.com',
    city: 'Jakarta'
})

// Buat node Person kedua
CREATE (sari:Person {
    name: 'Sari Dewi',
    age: 26,
    email: 'sari@email.com',
    city: 'Bandung'
})

// Buat node Person ketiga
CREATE (andi:Person {
    name: 'Andi Pratama',
    age: 30,
    email: 'andi@email.com',
    city: 'Jakarta'
})

// Buat node Company
CREATE (techcorp:Company {
    name: 'TechCorp Indonesia',
    industry: 'Technology',
    founded: 2015
})

// Buat node Product
CREATE (laptop:Product {
    name: 'Laptop Pro X',
    price: 15000000,
    category: 'Elektronik',
    stock: 50
})

CREATE (phone:Product {
    name: 'Phone Ultra',
    price: 8000000,
    category: 'Elektronik',
    stock: 200
})


// =============================================
// MEMBUAT RELATIONSHIPS
// =============================================

// Budi kenal Sari sejak 2020
MATCH (budi:Person {name: 'Budi Santoso'})
MATCH (sari:Person {name: 'Sari Dewi'})
CREATE (budi)-[:KNOWS {since: 2020, source: 'university'}]->(sari)

// Sari kenal Andi sejak 2021
MATCH (sari:Person {name: 'Sari Dewi'})
MATCH (andi:Person {name: 'Andi Pratama'})
CREATE (sari)-[:KNOWS {since: 2021}]->(andi)

// Budi juga kenal Andi
MATCH (budi:Person {name: 'Budi Santoso'})
MATCH (andi:Person {name: 'Andi Pratama'})
CREATE (budi)-[:KNOWS {since: 2019}]->(andi)

// Budi bekerja di TechCorp sebagai Engineer
MATCH (budi:Person {name: 'Budi Santoso'})
MATCH (tc:Company {name: 'TechCorp Indonesia'})
CREATE (budi)-[:WORKS_AT {role: 'Senior Engineer', since: 2020}]->(tc)

// Budi membeli Laptop
MATCH (budi:Person {name: 'Budi Santoso'})
MATCH (laptop:Product {name: 'Laptop Pro X'})
CREATE (budi)-[:PURCHASED {
    date: date('2026-01-15'),
    quantity: 1,
    rating: 5
}]->(laptop)

// Budi juga membeli Phone
MATCH (budi:Person {name: 'Budi Santoso'})
MATCH (phone:Product {name: 'Phone Ultra'})
CREATE (budi)-[:PURCHASED {
    date: date('2026-03-20'),
    quantity: 1,
    rating: 4
}]->(phone)


// =============================================
// MERGE: Create if not exists (idempotent)
// =============================================
MERGE (rina:Person {name: 'Rina Wati'})
ON CREATE SET rina.age = 25, rina.city = 'Surabaya'
ON MATCH SET rina.updated_at = datetime()

// MERGE untuk relationship
MATCH (budi:Person {name: 'Budi Santoso'})
MATCH (rina:Person {name: 'Rina Wati'})
MERGE (budi)-[r:KNOWS]->(rina)
ON CREATE SET r.since = 2024
ON MATCH SET r.last_seen = datetime()

3. Cypher — Dasar Query Language

Cypher adalah bahasa query deklaratif untuk Neo4j. Desainnya terinspirasi dari ASCII art — node digambarkan sebagai () dan relationship sebagai --> atau --. Ini membuat query Cypher sangat mudah dibaca.

Cypher — READ Operations
// =============================================
// MATCH — Mencari nodes
// =============================================

// Ambil semua node Person
MATCH (p:Person)
RETURN p

// Ambil semua node dengan property tertentu
MATCH (p:Person {city: 'Jakarta'})
RETURN p.name, p.age

// Filter dengan WHERE
MATCH (p:Person)
WHERE p.age > 25 AND p.city = 'Jakarta'
RETURN p.name, p.age, p.city

// Ambil semua node (tanpa filter)
MATCH (n)
RETURN labels(n), count(n) AS jumlah

// Ambil relationship tertentu
MATCH (p:Person)-[r:KNOWS]->(friend:Person)
RETURN p.name AS nama, friend.name AS teman, r.since AS kenal_sejak


// =============================================
// RETURN — Menentukan output
// =============================================

// Return specific properties
MATCH (p:Person)
RETURN p.name AS nama, p.age AS umur
ORDER BY p.age DESC
LIMIT 10

// Return distinct values
MATCH (p:Person)-[:WORKS_AT]->(c:Company)
RETURN DISTINCT c.name AS perusahaan

// Return as list
MATCH (p:Person)-[:PURCHASED]->(prod:Product)
RETURN p.name AS nama, collect(prod.name) AS produk_dibeli


// =============================================
// CREATE — Membuat data baru
// =============================================

// Buat node baru
CREATE (u:User {
    id: randomUUID(),
    name: 'User Baru',
    email: 'baru@email.com',
    created_at: datetime()
})
RETURN u

// Buat relationship baru
MATCH (a:Person {name: 'Budi Santoso'})
MATCH (b:Person {name: 'Rina Wati'})
CREATE (a)-[:MENTORS {since: 2024}]->(b)


// =============================================
// SET & REMOVE — Update properties
// =============================================

// Update property
MATCH (p:Person {name: 'Budi Santoso'})
SET p.age = 29, p.updated_at = datetime()
RETURN p

// Tambah label baru
MATCH (p:Person {name: 'Budi Santoso'})
SET p:PremiumUser:Verified

// Hapus property
MATCH (p:Person {name: 'Budi Santoso'})
REMOVE p.email


// =============================================
// DELETE — Menghapus data
// =============================================

// Hapus node (harus hapus relationship dulu!)
MATCH (p:Person {name: 'Test User'})
DETACH DELETE p

// Hapus relationship
MATCH (p:Person {name: 'Budi Santoso'})-[r:KNOWS]->(other:Person {name: 'Rina Wati'})
DELETE r

// Hapus semua node & relationships (HATI-HATI!)
// MATCH (n) DETACH DELETE n
⚠️ DELETE di Graph Database

Anda tidak bisa menghapus node yang masih punya relationship. Gunakan DETACH DELETE untuk menghapus node beserta semua relationship-nya. Atau hapus relationship terlebih dahulu sebelum menghapus node.

4. Pattern Matching & Traversal

Kekuatan utama graph database adalah pattern matching — mencari pola hubungan antar node. Cypher mendeskripsikan pola ini secara visual menggunakan sintaks yang intuitif.

Cypher — Pattern Matching
// =============================================
// BASIC PATTERNS
// =============================================

// Pattern: Siapa yang dikenal Budi?
MATCH (budi:Person {name: 'Budi Santoso'})-[:KNOWS]->(teman)
RETURN teman.name

// Pattern: Teman dari teman (2 hop)
MATCH (budi:Person {name: 'Budi Santoso'})-[:KNOWS*2]->(fof)
RETURN DISTINCT fof.name AS friend_of_friend

// Pattern: Variable length path (1-3 hop)
MATCH (budi:Person {name: 'Budi Santoso'})-[:KNOWS*1..3]->(connected)
RETURN DISTINCT connected.name

// Pattern: Shortest path antara 2 node
MATCH path = shortestPath(
    (budi:Person {name: 'Budi Santoso'})-[:KNOWS*]-(target:Person {name: 'Andi Pratama'})
)
RETURN path, length(path) AS degrees_of_separation


// =============================================
// BIDIRECTIONAL PATTERNS
// =============================================

// Relationship tanpa arah (kedua arah)
MATCH (p:Person)-[:KNOWS]-(other:Person)
WHERE p.name = 'Budi Santoso'
RETURN other.name

// Directed: Budi → teman
MATCH (p:Person)-[:KNOWS]->(other:Person)
RETURN p.name, other.name


// =============================================
// MULTI-PATTERN (menggabungkan beberapa pola)
// =============================================

// Budi kenal siapa, dan siapa yang beli produk yang sama
MATCH (budi:Person {name: 'Budi Santoso'})-[:PURCHASED]->(p:Product)
MATCH (other:Person)-[:PURCHASED]->(p)
WHERE other <> budi
RETURN other.name AS pembeli, p.name AS produk

// Budi dan temannya yang bekerja di perusahaan sama
MATCH (budi:Person {name: 'Budi Santoso'})-[:WORKS_AT]->(c:Company)
MATCH (colleague:Person)-[:WORKS_AT]->(c)
WHERE colleague <> budi
RETURN colleague.name AS rekan, c.name AS perusahaan


// =============================================
// OPTIONAL MATCH (LEFT JOIN equivalent)
// =============================================

// Ambil semua person, tampilkan perusahaan jika ada
MATCH (p:Person)
OPTIONAL MATCH (p)-[:WORKS_AT]->(c:Company)
RETURN p.name, COALESCE(c.name, 'Freelance') AS pekerjaan


// =============================================
// EXISTS — Cek keberadaan pattern
// =============================================

// Person yang pernah membeli sesuatu
MATCH (p:Person)
WHERE EXISTS {
    MATCH (p)-[:PURCHASED]->(:Product)
}
RETURN p.name


// =============================================
// NEGATION — Pattern yang TIDAK ada
// =============================================

// Person yang TIDAK punya relationship KNOWS
MATCH (p:Person)
WHERE NOT EXISTS {
    MATCH (p)-[:KNOWS]->(:Person)
}
RETURN p.name

// Person yang TIDAK pernah membeli apapun
MATCH (p:Person)
WHERE NOT EXISTS {
    MATCH (p)-[:PURCHASED]->(:Product)
}
RETURN p.name

5. Aggregation & Filtering

Cypher — Aggregation & Filtering
// =============================================
// AGGREGATION FUNCTIONS
// =============================================

// Hitung jumlah teman per orang
MATCH (p:Person)-[:KNOWS]->(teman:Person)
RETURN p.name, count(teman) AS jumlah_teman
ORDER BY jumlah_teman DESC

// Total pembelian per orang
MATCH (p:Person)-[r:PURCHASED]->(prod:Product)
RETURN p.name AS nama,
       count(prod) AS jumlah_produk,
       sum(prod.price * r.quantity) AS total_belanja,
       avg(prod.price) AS rata_harga,
       min(prod.price) AS harga_termurah,
       max(prod.price) AS harga_termahal
ORDER BY total_belanja DESC

// Collect: kumpulkan values ke list
MATCH (p:Person)-[:KNOWS]->(teman:Person)
RETURN p.name AS nama,
       collect(teman.name) AS daftar_teman,
       count(teman) AS jumlah

// Count distinct
MATCH (p:Person)-[:PURCHASED]->(prod:Product)
RETURN prod.category AS kategori,
       count(DISTINCT p.name) AS jumlah_pembeli


// =============================================
// HAVING equivalent: WHERE after aggregation
// =============================================

// Teman dengan lebih dari 1 hubungan
MATCH (p:Person)-[:KNOWS]->(teman:Person)
WITH p, count(teman) AS jumlah
WHERE jumlah > 1
RETURN p.name, jumlah

// Atau gunakan HAVING pattern dengan WITH
MATCH (p:Person)-[:KNOWS]->(teman:Person)
WITH p, count(teman) AS jumlah_teman
WHERE jumlah_teman >= 2
RETURN p.name, jumlah_teman
ORDER BY jumlah_teman DESC


// =============================================
// WITH: Pipeline chaining
// =============================================

// Step 1: Hitung total belanja per orang
// Step 2: Filter yang belanja > 10jt
// Step 3: Return dengan info lengkap
MATCH (p:Person)-[r:PURCHASED]->(prod:Product)
WITH p, sum(prod.price * r.quantity) AS total
WHERE total > 10000000
RETURN p.name AS nama, total AS total_belanja
ORDER BY total DESC


// =============================================
// UNWIND: Expand list ke rows
// =============================================

// Membuat nodes dari list
WITH ['Jakarta', 'Bandung', 'Surabaya', 'Yogyakarta'] AS kota_list
UNWIND kota_list AS kota
CREATE (k:Kota {name: kota})
RETURN k


// =============================================
// ORDER BY, SKIP, LIMIT
// =============================================

// Pagination di graph
MATCH (p:Person)
RETURN p.name, p.age
ORDER BY p.name ASC
SKIP 0 LIMIT 10  // Halaman 1

// Sorting multi-field
MATCH (p:Person)-[:PURCHASED]->(prod:Product)
RETURN p.name, prod.name, prod.price
ORDER BY p.name ASC, prod.price DESC

6. Advanced: Path, Algorithms & APOC

Cypher — Advanced Queries
// =============================================
// PATH QUERIES
// =============================================

// Semua path antara 2 node (max 5 hop)
MATCH path = (a:Person {name: 'Budi Santoso'})
    -[:KNOWS*1..5]-
    (b:Person {name: 'Andi Pratama'})
RETURN path, length(path) AS panjang
ORDER BY panjang

// All simple paths (no repeated nodes)
MATCH path = allShortestPaths(
    (a:Person {name: 'Budi Santoso'})-[:KNOWS*]-(b:Person {name: 'Andi Pratama'})
)
RETURN path

// Ring/cycle detection
MATCH path = (p:Person)-[:KNOWS*3..6]->(p)
RETURN p.name, length(path) AS cycle_length


// =============================================
// GRAPH ALGORITHMS (GDS - Graph Data Science)
// =============================================

// Degree Centrality: Siapa yang paling banyak hubungan?
MATCH (p:Person)
OPTIONAL MATCH (p)-[:KNOWS]-(other:Person)
RETURN p.name, count(other) AS degree
ORDER BY degree DESC

// PageRank: Siapa yang paling "influential"?
// (Memerlukan GDS library)
// CALL gds.pageRank.stream('myGraph')
// YIELD nodeId, score
// RETURN gds.util.asNode(nodeId).name AS name, score
// ORDER BY score DESC

// Community Detection: Grup mana saja?
// CALL gds.louvain.stream('myGraph')
// YIELD nodeId, communityId
// RETURN communityId, collect(gds.util.asNode(nodeId).name) AS members

// Shortest Path dengan Dijkstra
// MATCH (start:Person {name: 'Budi Santoso'}), (end:Person {name: 'Andi Pratama'})
// CALL gds.shortestPath.dijkstra.stream('myGraph', {
//     sourceNode: start,
//     targetNode: end,
//     relationshipWeightProperty: 'weight'
// })
// YIELD index, sourceNode, targetNode, totalCost, path
// RETURN path, totalCost


// =============================================
// APOC LIBRARY (Advanced Procedures)
// =============================================

// Generate data dummy
// CALL apoc.create.node(['Person'], {name: 'Random Person ' + apoc.create.uuid()})
// YIELD node RETURN node

// Export to JSON
// CALL apoc.export.json.all("export.json", {})
// YIELD file, source, format, nodes, relationships
// RETURN file, nodes, relationships

// Path expansion dengan kontrol lebih detail
// CALL apoc.path.expand(
//     startNode,
//     'KNOWS|WORKS_AT>',  // relationship types
//     'Person|Company',    // end node labels
//     1,                   // min depth
//     5                    // max depth
// )
// YIELD path RETURN path

7. Use Case: Social Network & Recommendation

Cypher — Social Network Use Case
// =============================================
// SOCIAL NETWORK: Rekomendasi Teman
// =============================================

// "People You May Know": teman dari teman yang belum jadi teman
MATCH (me:Person {name: 'Budi Santoso'})-[:KNOWS]->(friend)-[:KNOWS]->(fof:Person)
WHERE NOT (me)-[:KNOWS]->(fof)
  AND me <> fof
RETURN fof.name AS rekomendasi,
       count(friend) AS mutual_friends,
       collect(friend.name) AS via
ORDER BY mutual_friends DESC
LIMIT 5


// =============================================
// RECOMMENDATION ENGINE
// =============================================

// "Orang yang beli produk yang sama juga beli..."
MATCH (me:Person {name: 'Budi Santoso'})-[:PURCHASED]->(p:Product)
MATCH (other:Person)-[:PURCHASED]->(p)
WHERE other <> me
MATCH (other)-[:PURCHASED]->(recommendation:Product)
WHERE NOT (me)-[:PURCHASED]->(recommendation)
RETURN recommendation.name AS produk_rekomendasi,
       recommendation.price AS harga,
       count(other) AS dibeli_oleh,
       collect(DISTINCT other.name) AS pembeli_lain
ORDER BY dibeli_oleh DESC
LIMIT 5


// =============================================
// FRAUD DETECTION: Pola Mencurigakan
// =============================================

// Deteksi: Banyak transaksi cepat dari IP yang sama
MATCH (u:User)-[:USED_IP]->(ip:IP)<-[:USED_IP]-(other:User)
WHERE u <> other
MATCH (u)-[:TRANSACTION]->(t:Transaction)
WHERE t.amount > 5000000
  AND t.date > datetime() - duration('P7D')
RETURN u.name AS user_suspect,
       ip.address AS shared_ip,
       count(t) AS high_value_transactions,
       other.name AS other_user
ORDER BY high_value_transactions DESC


// =============================================
// KNOWLEDGE GRAPH: Semantic Search
// =============================================

// "Siapa yang bekerja di bidang Technology di Jakarta?"
MATCH (p:Person)-[:WORKS_AT]->(c:Company {industry: 'Technology'})
WHERE p.city = 'Jakarta'
RETURN p.name, c.name, p.age
ORDER BY p.age

// "Apa saja produk yang dibeli orang dari Jakarta?"
MATCH (p:Person {city: 'Jakarta'})-[:PURCHASED]->(prod:Product)
RETURN prod.name AS produk,
       prod.category AS kategori,
       count(p) AS jumlah_pembeli,
       avg(prod.price) AS rata_harga
ORDER BY jumlah_pembeli DESC


// =============================================
// ANALYTICS: Degree Distribution
// =============================================

// Distribusi jumlah koneksi per user
MATCH (p:Person)
OPTIONAL MATCH (p)-[r]-()
WITH p, count(r) AS connections
RETURN connections AS jumlah_koneksi,
       count(p) AS jumlah_orang
ORDER BY connections

8. Best Practices & Kapan Menggunakan

Neo4j vs Relasional: Kapan Pilih Mana?

Aspek Neo4j (Graph) MySQL/PG (Relational)
Hubungan kompleks✅ Sangat cepat❌ JOIN mahal untuk deep traversal
Data terstruktur tabular❌ Overhead✅ Optimal
ACID transactions✅ Didukung (sejak 3.5+)✅ Penuh
Schema flexibility✅ Schema-free❌ Schema rigid
Shortest path✅ Built-in❌ Sangat kompleks
Reporting/Aggregasi⚠️ Biasa✅ Optimasi baik
Ekosistem tools⚠️ Lebih kecil✅ Sangat besar
Skalabilitas horizontal⚠️ Causal clustering✅ Sharding mature
💡 Best Practices Neo4j
  • Buat index pada property yang sering di-MATCHCREATE INDEX FOR (p:Person) ON (p.name)
  • Hindari Cartesian product — pastikan setiap MATCH terhubung
  • Gunakan parameterized queriesWHERE p.name = $name
  • Batasi depth traversal[:KNOWS*1..3] bukan [:KNOWS*]
  • Monitor query — gunakan :PROFILE atau :EXPLAIN di Neo4j Browser
  • Hindari supernodes — node dengan ratusan ribu relationship
  • Gunakan MERGE bukan CREATE untuk data idempotent
  • Batch operations — gunakan UNWIND untuk bulk create

9. Quiz Pemahaman

Uji pemahaman Anda tentang Neo4j dan Cypher!

1. Apa itu "node" dalam graph database?

2. Dalam Cypher, apa arti (p:Person)-[:KNOWS]->(f)?

3. Mengapa DELETE node gagal di Neo4j?

4. Apa keunggulan utama graph database dibanding relational untuk social network?

5. Fungsi apa yang digunakan untuk mengumpulkan hasil ke list dalam Cypher?

Rangkuman

📝 Poin Penting
  • Graph Database — menyimpan data sebagai node dan relationship, bukan tabel
  • Cypher — bahasa query yang intuitif dengan pola ASCII art (a)-[:KNOWS]->(b)
  • Pattern Matching — kekuatan utama: temukan pola hubungan kompleks dengan mudah
  • Variable Length Path[:KNOWS*1..3] untuk traversal multi-hop
  • MERGE — create-if-not-exists untuk data idempotent
  • Best untuk — social network, recommendation, fraud detection, knowledge graph
  • Hindari untuk — reporting heavy, data tabular sederhana, aggregasi besar-besaran