Melakukan Query Hubungan Video dengan Apache AGE pada Postgres
Database relasional kesulitan menangani hubungan yang mendalam.
Di TrendVidStream, kami mengelola katalog judul streaming di delapan wilayah. Awalnya kami menggunakan SQLite dengan FTS5. Ini bekerja dengan baik untuk pencarian teks lengkap (full-text search) dan penerapan yang sederhana.
Masalah muncul ketika pengguna mengajukan pertanyaan kompleks. Mereka ingin tahu: "Apa lagi yang berjarak dua atau tiga lompatan (hops) dari film thriller dengan sutradara dan aktor tertentu ini?"
Dalam SQL, hal ini memerlukan banyak self-join. Setiap tambahan lompatan membuat query lebih sulit dipelihara dan lebih lambat dijalankan. Join fan-out menjadi sebuah mimpi buruk.
Kami mengatasi hal ini dengan menambahkan lapisan graf menggunakan ekstensi Apache AGE pada PostgreSQL.
Berikut adalah alasan mengapa pembagian ini berhasil:
• Anda tetap menggunakan PostgreSQL. Anda menggunakan koneksi, transaksi, dan alat pencadangan yang sama. Anda tidak memerlukan database terpisah seperti Neo4j. • Anda mencampur data graf dan relasional. Anda dapat menjalankan query Cypher dan menggabungkan hasilnya dengan tabel SQL standar. • Anda menangani kedalaman variabel dengan mudah. Menemukan koneksi dalam satu hingga tiga lompatan adalah perintah sederhana di Cypher. • Anda menjaga kesederhanaan. Graf adalah proyeksi dari data Anda, bukan sumber kebenaran (source of truth) yang terpisah.
Model kami menggunakan empat label vertex:
- Video
- Person
- Platform
- Region
Kami menggunakan tipe edge tertentu seperti SIMILAR_TO, WORKED_ON, dan AVAILABLE_IN.
Satu pelajaran penting: selalu buat indeks pada titik masuk (entry points) Anda. Kami mengindeks properti ext_id pada vertex Video. Tanpa ini, setiap traversal akan dimulai dengan pemindaian sekuensial (sequential scan) yang lambat.
Hasilnya adalah query yang bersih dan mudah dibaca untuk rekomendasi:
SELECT * FROM cypher('discovery', $$ MATCH (seed:Video {ext_id: 'vid_8842'}) MATCH (seed)-[:SIMILAR_TO|WORKED_ON*1..3]-(rec:Video)-[:AVAILABLE_IN]->(:Region {code: 'DE'}) WHERE rec.ext_id <> 'vid_8842' RETURN DISTINCT rec.ext_id, rec.title, rec.year LIMIT 24 $$) AS (ext_id agtype, title agtype, year agtype);
Query ini menemukan video terkait dalam tiga lompatan yang tersedia di Jerman. Dalam SQL, ini akan menjadi tumpukan join yang sangat besar. Dalam Cypher, ini hanyalah sebuah pola sederhana.
Kami tetap menggunakan SQLite untuk pencarian teks dan menggunakan AGE untuk konektivitas. Setiap alat melakukan apa yang terbaik baginya.
