Pola Adjacency List DynamoDB
Sebuah graf hanyalah node dan edge, dan pola adjacency list menyimpan keduanya
sebagai item biasa dalam satu tabel. Setiap edge menjadi sebuah baris yang
partition key-nya adalah node sumber dan sort key-nya adalah targetnya. Meng-query
sebuah partition mendaftarkan setiap tetangga — pengganti DynamoDB untuk sebuah
JOIN pada tabel join.
Apa itu pola adjacency list DynamoDB?
Pola adjacency list memodelkan sebuah graf sebagai item edge dalam satu tabel: setiap relasi (A follow B) adalah sebuah baris yang ber-key sumber pada partition key dan target pada sort key. Meng-query sebuah partition mendaftarkan setiap tetangga, dan sebuah GSI terbalik membalik relasinya — tanpa join, tanpa scan, kedua arah dalam satu query.
- Edge adalah item. Modelkan setiap relasi (user A follow user B) sebagai item-nya sendiri ber-key sumber pada partition key, target pada sort key.
- Satu arah gratis; arah lainnya butuh GSI. Base table menjawab "siapa yang A follow?". Sebuah indeks terbalik menjawab "siapa yang follow A?".
- Tanpa join, tanpa scan. Kedua arah adalah satu
Queryterhadap sebuah partition yang diketahui — tidak pernah sebuahScanseluruh tabel. - Ia adalah primitif many-to-many. Follow, keanggotaan, like, pertemanan — graf apa pun di mana satu entitas terhubung ke banyak lainnya cocok dengan bentuk ini.
Bingkai sebagai pola akses
Datang dari SQL, sebuah graf follow adalah tabel join: follows(follower_id, followee_id). Untuk mendaftarkan follower seseorang Anda mengindeks satu kolom;
untuk mendaftarkan siapa yang mereka follow Anda mengindeks kolom lainnya.
DynamoDB tidak punya join, jadi Anda mendesain key-nya untuk melayani tiap
pembacaan langsung.
Tuliskan pembacaannya lebih dulu. Untuk graf follow sosial:
- Siapa yang user A follow? (daftar following mereka)
- Siapa yang follow user A? (daftar followers mereka)
- Apakah A follow B? (sebuah lookup titik tunggal)
Key-nya ada semata untuk menjawab daftar itu. Buat ia benar dan setiap pembacaan
adalah satu Query atau GetItem.
Modelkan edge sebagai item
Gunakan nama key generik agar tabel bisa menampung lebih dari satu tipe entitas, dan encode tipe node di nilainya. Sebuah follow edge tampak seperti ini:
| PK | SK | createdAt | edgeType |
|---|---|---|---|
| ACTOR#alice | TARGET#bob | 1718900000 | FOLLOWS |
| ACTOR#alice | TARGET#carol | 1718900100 | FOLLOWS |
| ACTOR#dave | TARGET#bob | 1718900200 | FOLLOWS |
PK = ACTOR#alice adalah sumber edge; SK = TARGET#bob adalah siapa yang ia
follow. Satu Query PK = "ACTOR#alice" mengembalikan setiap akun yang Alice
follow dalam satu pembacaan yang ditagih — seluruh daftar following-nya, tanpa
join.
Setiap edge ditulis sekali, dalam arah "siapa yang saya follow". Arah balik ("siapa yang follow saya") adalah bagian yang base table tak bisa jawab — belum.
Telusuri arah lainnya dengan GSI
Base table ber-key sumber-dulu, jadi ia tak bisa menjawab "siapa yang follow Bob?" tanpa scan. Tambahkan sebuah global secondary index yang membalik key-nya: proyeksikan target ke partition key indeks dan sumber ke sort key indeks.
| GSI1PK | GSI1SK | (item base) | |
|---|---|---|---|
| TARGET#bob | ACTOR#alice | ACTOR#alice → TARGET#bob | |
| TARGET#bob | ACTOR#dave | ACTOR#dave | → TARGET#bob |
| TARGET#carol | ACTOR#alice | ACTOR#alice → TARGET#carol |
Kini Query GSI1 WHERE GSI1PK = "TARGET#bob" mendaftarkan semua orang yang
follow Bob — alice dan dave — dalam satu pembacaan. Item edge yang sama
melayani kedua arah: base table adalah following, indeks adalah followers.
Anda menulis setiap edge sekali dan mendapat kedua query gratis.
Ini persis pola yang AWS dokumentasikan dalam panduan best-practice DynamoDB-nya untuk memodelkan relasi many-to-many dan data graf — simpan edge sebagai item, lalu gunakan sebuah GSI untuk membalik relasinya.
Periksa satu edge dengan murah
"Apakah Alice follow Bob?" tidak butuh salah satu daftar. Karena edge-nya ber-key
PK = ACTOR#alice, SK = TARGET#bob, itu adalah GetItem langsung — pembacaan
termurah yang DynamoDB tawarkan, tanpa Query, tanpa indeks.
Untuk menulis follow secara idempoten dan menghindari penghitungan ganda, jaga
PutItem dengan sebuah kondisi bahwa edge-nya belum ada:
attribute_not_exists(PK)
Anda bisa merakit kondisi itu — dan nilai key yang ter-marshal — dengan
DynamoDB expression builder alih-alih
menulis sendiri ConditionExpression dan ExpressionAttributeValues.
Lakukan di DynoTable
Saat Anda menjelajahi tabel, edge untuk satu actor menumpuk di bawah sebuah partition key sebagai satu item collection, dan beralih ke tampilan GSI menunjukkan daftar followers yang terbalik — dua paruh dari relasi berdampingan.

Jebakan
Partition selebritas. Seorang user dengan jutaan follower memusatkan setiap
follower edge di bawah satu partition GSI1PK = TARGET#<star>. Pembacaan
collection itu terpaginasi dan bisa berjalan panas. Untuk graf yang fan-out-heavy,
shard hot key-nya (mis. TARGET#bob#0..N) atau denormalisasi penghitungan agar
Anda tak perlu membaca ulang seluruh daftar.
Menyimpan penghitungan pada edge. Sebuah count follower bukanlah sebuah edge — jangan turunkan ia dengan membaca dan menghitung seluruh partition pada setiap tampilan profil. Pelihara sebuah atribut penghitung pada item user dan perbarui ia secara transaksional bersama edge-nya.
Lupa bahwa penulisan balik tidak dibutuhkan di sini. Sebuah varian adjacency-list klasik menulis edge dua kali dengan id ditukar. Dengan sebuah GSI flip-key Anda menulisnya sekali dan membiarkan indeks memmaterialisasi baliknya — lebih sedikit penulisan, tanpa penyimpangan antara dua salinan.
Langkah berikutnya
Adjacency list adalah balok bangunan relasi dari
single-table design; indeks yang membalik adalah
sebuah GSI, bukan LSI, karena partition key-nya berubah.
Dan setiap pembacaan di sini adalah sebuah Query atau GetItem pada key yang
diketahui — tidak pernah jebakan Scan.
Bangun ekspresi kondisi dan key dengan DynamoDB expression builder, dan unduh DynoTable untuk memodelkan graf follow terhadap tabel Anda sendiri dan amati kedua arah terselesaikan dalam satu pembacaan.


