Terjemahan disediakan oleh mesin penerjemah. Jika konten terjemahan yang diberikan bertentangan dengan versi bahasa Inggris aslinya, utamakan versi bahasa Inggris.
Contoh semantik transaksi Neptunus
Contoh berikut menggambarkan kasus penggunaan yang berbeda untuk semantik transaksi di Amazon Neptune.
Topik
Contoh 1 - Memasukkan Properti Hanya Jika Tidak Ada
Misalkan Anda ingin memastikan bahwa properti diatur hanya sekali. Sebagai contoh, misalkan beberapa kueri mencoba untuk menetapkan kepada seseorang skor kredit secara bersamaan. Anda hanya ingin satu instans dari properti dimasukkan, dan kueri lainnya gagal karena properti telah ditetapkan.
# GREMLIN: g.V('person1').hasLabel('Person').coalesce(has('creditScore'), property('creditScore', 'AAA+')) # SPARQL: INSERT { :person1 :creditScore "AAA+" .} WHERE { :person1 rdf:type :Person . FILTER NOT EXISTS { :person1 :creditScore ?o .} }
Langkah property()
Gremlin menyisipkan properti dengan kunci dan nilai yang diberikan. Langkah coalesce()
mengeksekusi argumen pertama di langkah pertama, dan jika gagal, maka mengeksekusi langkah kedua:
Sebelum memasukkan nilai properti creditScore
untuk vertex person1
yang diberikan, transaksi harus coba membaca kemungkinan tidak adanya nilai creditScore
untuk person1
. Ini mencoba membaca kunci rentang SP
untuk S=person1
dan P=creditScore
dalam SPOG
indeks tempat nilai creditScore
ada atau akan ditulis.
Mengambil kunci rentang ini mencegah transaksi bersamaan apapun dari memasukkan nilai creditScore
secara bersamaan. Ketika ada beberapa transaksi paralel, paling banyak salah satu dari transaksi tersebut dapat memperbarui nilai pada suatu waktu. Ini mengeliminasi anomali lebih dari satu properti creditScore
yang dibuat.
Contoh 2 - Menegaskan Bahwa Nilai Properti Adalah Unik secara Global
Misalkan Anda ingin memasukkan seseorang dengan nomor Jaminan Sosial sebagai kunci utama. Anda ingin kueri mutasi Anda menjamin bahwa, pada tingkat global, tidak ada orang lain dalam database memiliki nomor Jaminan Sosial yang sama:
# GREMLIN: g.V().has('ssn', 123456789).fold() .coalesce(__.unfold(), __.addV('Person').property('name', 'John Doe').property('ssn', 123456789')) # SPARQL: INSERT { :person1 rdf:type :Person . :person1 :name "John Doe" . :person1 :ssn 123456789 .} WHERE { FILTER NOT EXISTS { ?person :ssn 123456789 } }
Contoh ini sama dengan yang sebelumnya. Perbedaan utamanya adalah bahwa kunci rentang diambil pada indeks POGS
ketimbang indeks SPOG
.
Transaksi mengeksekusi kueri harus membaca pola, ?person :ssn 123456789
, di mana posisi P
dan O
terikat. Kunci rentang diambil pada indeks POGS
untuk P=ssn
dan O=123456789
.
Jika pola itu ada, tidak ada tindakan yang diambil.
Jika tidak ada, penguncian mencegah setiap transaksi bersamaan dari menyisipkan nomor Jaminan Sosial juga
Contoh 3 - Mengubah Properti Jika Properti Lain Memiliki Nilai Tertentu
Misalkan berbagai peristiwa dalam game memindahkan seseorang dari tingkat satu ke tingkat dua, dan menugaskan mereka properti level2Score
baru yang diatur ke nol. Anda harus yakin bahwa beberapa instans yang bersamaan dari transaksi tersebut tidak dapat membuat beberapa instans dari properti skor tingkat-dua. Kueri di Gremlin dan SPARQL mungkin terlihat seperti berikut ini.
# GREMLIN: g.V('person1').hasLabel('Person').has('level', 1) .property('level2Score', 0) .property(Cardinality.single, 'level', 2) # SPARQL: DELETE { :person1 :level 1 .} INSERT { :person1 :level2Score 0 . :person1 :level 2 .} WHERE { :person1 rdf:type :Person . :person1 :level 1 .}
Di Gremlin, ketika Cardinality.single
ditentukan, langkah property()
menambahkan properti baru atau menggantikan nilai properti yang ada dengan nilai baru yang ditentukan.
Setiap pembaruan ke nilai properti, seperti meningkatkan level
dari 1 sampai 2, diimplementasikan sebagai penghapusan catatan saat ini dan penyisipan catatan baru dengan nilai properti baru. Dalam hal ini, catatan dengan tingkat nomor 1 dihapus dan catatan dengan tingkat nomor 2 dimasukkan kembali.
Untuk transaksi agar dapat menambah level2Score
dan memperbarui level
dari 1 sampai 2, transaksi harus terlebih dahulu memvalidasi bahwa nilai level
saat ini sama dengan 1. Dengan demikian, dibutuhkan kunci rentang pada prefiks SPO
untuk S=person1
, P=level
, dan O=1
dalam indeks SPOG
. Kunci ini mencegah transaksi yang bersamaan menghapus versi 1 tiga kali lipat, dan sebagai hasilnya, tidak ada pembaruan bersamaan yang bertentangan dapat terjadi.
Contoh 4 - Mengganti Properti yang Ada
Peristiwa tertentu dapat memperbarui nilai kredit seseorang ke nilai baru (di sini BBB
). Tetapi Anda ingin memastikan bahwa peristiwa bersamaan dari jenis tersebut tidak dapat membuat beberapa properti skor kredit untuk seseorang.
# GREMLIN: g.V('person1').hasLabel('Person') .sideEffect(properties('creditScore').drop()) .property('creditScore', 'BBB') # SPARQL: DELETE { :person1 :creditScore ?o .} INSERT { :person1 :creditScore "BBB" .} WHERE { :person1 rdf:type :Person . :person1 :creditScore ?o .}
Kasus ini mirip dengan contoh 3, kecuali bahwa alih-alih mengunci SPO
awalan, Neptunus mengunci SP
awalan dengan dan hanya. S=person1
P=creditScore
Hal ini mencegah transaksi bersamaan dari memasukkan atau menghapus setiap triple dengan properti creditScore
untuk subjek person1
.
Contoh 5 - Menghindari Properti atau Edge Menggantung
Pembaruan pada entitas tidak harus meninggalkan elemen menggantung, yaitu properti atau edge yang terkait dengan entitas yang tidak diketik. Ini hanya masalahSPARQL, karena Gremlin memiliki batasan bawaan untuk mencegah elemen menggantung.
# SPARQL: tx1: INSERT { :person1 :age 23 } WHERE { :person1 rdf:type :Person } tx2: DELETE { :person1 ?p ?o }
Kueri INSERT
harus membaca dan mengunci prefiks SPO
dengan S=person1
, P=rdf:type
, dan O=Person
dalam indeks SPOG
. Penguncian mencegah kueri DELETE
dari berhasilnya secara paralel.
Dalam perlombaan antara query DELETE
mencoba untuk menghapus rekaman :person1 rdf:type :Person
dan query INSERT
membaca catatan dan membuat kunci rentang di SPO
dalam Indeks SPOG
, hasil berikut ini mungkin:
Jika kueri
INSERT
melakukan sebelum kueriDELETE
membaca dan menghapus semua catatan untuk:person1
,:person1
dihapus seluruhnya dari database, termasuk catatan yang baru dimasukkan.Jika query
DELETE
melakukan sebelum kueriINSERT
coba membaca catatan:person1 rdf:type :Person
, pembacaan mengamati perubahan yang dilakukan. Artinya, tidak menemukan catatan:person1 rdf:type :Person
apapun dan karenanya menjadi no-op.Jika
INSERT
kueri dibaca sebelumDELETE
kueri dilakukan,:person1 rdf:type :Person
triple dikunci danDELETE
kueri diblokir hingga INSERT kueri dilakukan, seperti pada kasus pertama sebelumnya.Jika bacaan
DELETE
membaca sebelum kueriINSERT
, dan kueriINSERT
mencoba untuk membaca dan mengunci prefiksSPO
untuk catatan, maka konflik terdeteksi. Hal ini karena triple telah ditandai untuk dihapus, danINSERT
kemudian gagal.
Dalam semua urutan kemungkinan yang berbeda dari peristiwa ini, tidak ada edge menggantung dibuat.