Menyimpan Data di Datastore


Bagian dari panduan kode Buku Tamu Python ini menunjukkan cara menyimpan data terstruktur di Datastore. Dengan App Engine dan Datastore, Anda tidak perlu mengkhawatirkan distribusi, replikasi, dan load balancing data. Hal tersebut dilakukan untuk Anda di belakang API sederhana, dan Anda juga mendapatkan mesin kueri serta transaksi yang canggih.

Halaman ini adalah bagian dari tutorial multi-halaman. Untuk memulai dari awal dan melihat petunjuk penyiapan, buka Membuat Buku Tamu.

Menyimpan salam yang dikirimkan

Data ditulis ke Datastore dalam objek yang dikenal sebagai entity. Setiap entity memiliki kunci yang mengidentifikasinya secara unik. Secara opsional, entity dapat menetapkan entity lain sebagai induknya; entity pertama adalah turunan entity induk. Dengan demikian, entity dalam penyimpanan data membentuk ruang berstruktur hierarkis yang mirip dengan struktur direktori sistem file. Untuk informasi mendetail, lihat Membuat Struktur Data untuk Konsistensi Kuat.

App Engine menyertakan API pemodelan data untuk Python. Untuk menggunakan API pemodelan data, aplikasi contoh mengimpor modul google.appengine.ext.ndb. Setiap salam mencakup nama penulis, konten pesan, serta tanggal dan waktu pesan diposting. Aplikasi menampilkan pesan dalam urutan kronologis. Kode berikut mendefinisikan model data:

class Author(ndb.Model):
    """Sub model for representing an author."""
    identity = ndb.StringProperty(indexed=False)
    email = ndb.StringProperty(indexed=False)

class Greeting(ndb.Model):
    """A main model for representing an individual Guestbook entry."""
    author = ndb.StructuredProperty(Author)
    content = ndb.StringProperty(indexed=False)
    date = ndb.DateTimeProperty(auto_now_add=True)

Kode ini menentukan model Greeting dengan tiga properti: author yang nilainya adalah objek Author dengan alamat email dan identitas penulis, content yang nilainya adalah string , dan date yang nilainya adalah datetime.datetime.

Beberapa konstruktor properti mengambil parameter untuk mengonfigurasi perilakunya lebih lanjut. Meneruskan konstruktor ndb.StringProperty parameter indexed=False menyatakan bahwa nilai untuk properti ini tidak akan diindeks. Tindakan ini akan menyimpan penulisan yang tidak diperlukan karena aplikasi tidak pernah menggunakan properti tersebut dalam kueri. Meneruskan parameter auto_now_add=True ke konstruktor ndb.DateTimeProperty akan mengonfigurasi model untuk secara otomatis memberikan stempel datetime pada objek baru saat objek dibuat, jika aplikasi tidak memberikan nilai. Untuk mengetahui daftar lengkap jenis properti dan opsinya, lihat Properti NDB.

Aplikasi ini menggunakan model data untuk membuat objek Greeting baru dan memasukkannya ke dalam Datastore. Pengendali Guestbook membuat salam baru dan menyimpannya ke penyimpanan data:

class Guestbook(webapp2.RequestHandler):

    def post(self):
        # We set the same parent key on the 'Greeting' to ensure each
        # Greeting is in the same entity group. Queries across the
        # single entity group will be consistent. However, the write
        # rate to a single entity group should be limited to
        # ~1/second.
        guestbook_name = self.request.get('guestbook_name',
                                          DEFAULT_GUESTBOOK_NAME)
        greeting = Greeting(parent=guestbook_key(guestbook_name))

        if users.get_current_user():
            greeting.author = Author(
                    identity=users.get_current_user().user_id(),
                    email=users.get_current_user().email())

        greeting.content = self.request.get('content')
        greeting.put()

        query_params = {'guestbook_name': guestbook_name}
        self.redirect('/?' + urllib.urlencode(query_params))

Pengendali Guestbook ini membuat objek Greeting baru, lalu menetapkan properti author dan content-nya dengan data yang diposting oleh pengguna. Induk dari Greeting adalah entity Guestbook. Anda tidak perlu membuat entity Guestbook sebelum menetapkannya menjadi induk entity lain. Dalam contoh ini, induk digunakan sebagai placeholder untuk tujuan transaksi dan konsistensi. Lihat halaman Transaksi untuk informasi selengkapnya. Objek yang memiliki ancestor yang sama berada dalam entity group yang sama. Kode tidak menetapkan properti date, jadi date secara otomatis ditetapkan ke saat ini, menggunakan auto_now_add=True.

Terakhir, greeting.put() menyimpan objek baru ke penyimpanan data. Jika memperoleh objek ini dari kueri, put() akan mengupdate objek yang ada. Karena kita membuat objek ini dengan konstruktor model, put() akan menambahkan objek baru ke penyimpanan data.

Karena pembuatan kueri di Datastore sangat konsisten hanya dalam entity group, kode ini menetapkan semua salam dari satu buku ke entity group yang sama dengan menetapkan induk yang sama untuk setiap salam. Artinya, pengguna selalu melihat salam segera setelah ditulis. Namun, tingkat penulisan ke entity group yang sama dibatasi untuk satu penulisan ke entity group per detik. Saat mendesain aplikasi, Anda harus mengingat fakta ini. Perlu diperhatikan bahwa menggunakan layanan seperti Memcache, Anda dapat mengurangi kemungkinan pengguna melihat hasil yang tidak berlaku saat membuat kueri di seluruh entity group setelah penulisan.

Mengambil salam yang dikirim

Datastore memiliki mesin kueri yang canggih untuk model data. Karena Datastore bukan database relasional tradisional, kueri tidak ditentukan menggunakan SQL. Sebagai gantinya, data dikueri dengan salah satu dari dua cara berikut: menggunakan Kueri Datastore, atau menggunakan bahasa kueri mirip SQL yang disebut GQL. Untuk mengakses rangkaian lengkap kemampuan kueri Datastore, sebaiknya gunakan kueri melalui GQL.

Pengendali MainPage mengambil dan menampilkan salam yang dikirimkan sebelumnya. Panggilan greetings_query.fetch(10) menjalankan kueri.

Selengkapnya tentang indeks Datastore

Setiap kueri pada Datastore dikomputasi dari satu atau beberapa indeks, yaitu tabel yang memetakan nilai properti yang diurutkan ke kunci entity. Inilah cara App Engine menampilkan hasil dengan cepat, terlepas dari ukuran penyimpanan data aplikasi Anda. Banyak kueri dapat dikomputasi dari indeks bawaan, tetapi untuk kueri yang lebih kompleks, Datastore memerlukan indeks kustom. Tanpa indeks kustom, Datastore tidak dapat mengeksekusi kueri ini secara efisien.

Misalnya, aplikasi Buku Tamu memfilter menurut buku tamu, dan pesanan menurut tanggal, menggunakan kueri ancestor dan tata urutan. Hal ini memerlukan indeks kustom untuk ditentukan dalam file index.yaml aplikasi. Anda dapat mengedit file ini secara manual, atau Anda dapat mengelolanya secara otomatis dengan menjalankan kueri di aplikasi secara lokal. Setelah indeks ditentukan di index.yaml, men-deploy aplikasi juga akan men-deploy informasi indeks kustom.

Definisi kueri di index.yaml akan terlihat seperti ini:

indexes:
- kind: Greeting
  ancestor: yes
  properties:
  - name: date
    direction: desc

Anda dapat membaca semua hal tentang indeks Datastore di halaman Indeks Datastore. Anda dapat membaca tentang spesifikasi yang sesuai untuk file index.yaml di Konfigurasi Indeks Datastore Python.