Kueri Proyeksi

Catatan: Developer yang membuat aplikasi baru sangat dianjurkan untuk menggunakan Library Klien NDB, yang memiliki beberapa manfaat dibandingkan dengan library klien ini, seperti menyimpan entity dalam cache secara otomatis melalui Memcache API. Jika saat ini Anda menggunakan Library Klien DB versi lama, baca Panduan Migrasi DB ke NDB

Sebagian besar kueri Datastore menampilkan seluruh entity sebagai hasilnya, tetapi sering kali aplikasi sebenarnya hanya tertarik pada beberapa properti entity. Kueri proyeksi memungkinkan Anda membuat kueri Datastore hanya untuk properti tertentu tersebut dari entity yang benar-benar Anda butuhkan, dengan latensi dan biaya yang lebih rendah daripada mengambil seluruh entity.

Kueri proyeksi mirip dengan kueri SQL berbentuk:

SELECT name, email, phone FROM CUSTOMER

Anda dapat menggunakan semua fitur pemfilteran dan pengurutan yang tersedia untuk kueri entity standar, sesuai dengan batasan yang dijelaskan di bawah. Kueri menampilkan hasil ringkas hanya dengan properti yang ditentukan (name, email, dan phone dalam contoh) yang diisi dengan nilai; semua properti lainnya tidak memiliki data.

Menggunakan kueri proyeksi di Python 2

Anda menentukan proyeksi dengan cara ini: Kueri proyeksi didukung oleh objek Query dan GqlQuery. Kedua class memerlukan impor ini:

from google.appengine.ext import db

Anda menentukan proyeksi dengan cara ini:

proj = db.Query(entity_name, projection=('property_1', 'property_2','property_n'))

proj = db.GqlQuery("SELECT property_1, property_2, property_n FROM entity_name")

Anda menangani hasil kueri ini seperti yang Anda lakukan untuk kueri entity standar: misalnya, dengan melakukan iterasi pada hasilnya.

Contoh kueri berikut adalah untuk properti title, read_path, dan date_written dari semua entri EventLog, yang diurutkan secara menaik menurut date_written, dan menulis nilai setiap properti ke log aplikasi:

for proj in db.GqlQuery("SELECT title, read_path, date_written" +
                        "FROM EventLog" +
                        "ORDER BY date_written ASC"):
  logging.info(proj.title)
  logging.info(proj.read_path)
  logging.info(proj.date_written)

Pengelompokan(eksperimental)

Kueri proyeksi dapat menggunakan kata kunci distinct untuk memastikan bahwa hanya hasil yang benar-benar unik yang akan ditampilkan dalam kumpulan hasil. Tindakan ini hanya akan menampilkan hasil pertama untuk entity dengan nilai yang sama untuk properti yang sedang diproyeksikan.

query = db.Query(projection=['A', 'B'], distinct=True).filter('B >', 1).order('-B, A')

Batasan proyeksi

Kueri proyeksi tunduk pada batasan berikut ini:

  • Hanya properti yang diindeks yang dapat diproyeksikan.

    Proyeksi tidak didukung untuk properti yang tidak diindeks, baik secara eksplisit maupun implisit. String teks panjang (Text) dan string byte panjang (Blob) tidak diindeks.

  • Properti yang sama tidak dapat diproyeksikan lebih dari sekali.

  • Properti yang direferensikan dalam filter kesetaraan (=) atau keanggotaan (IN) tidak dapat diproyeksikan.

    Misalnya,

    SELECT A FROM kind WHERE B = 1
    

    valid (properti yang diproyeksikan tidak digunakan dalam filter kesetaraan), begitu juga

    SELECT A FROM kind WHERE A > 1
    

    (bukan filter kesetaraan), tetapi

    SELECT A FROM kind WHERE A = 1
    

    (properti proyeksi yang digunakan dalam filter kesetaraan) tidak valid.

  • Hasil yang ditampilkan oleh kueri proyeksi tidak dapat disimpan kembali ke Datastore.

    Karena kueri menampilkan hasil yang hanya terisi sebagian, Anda tidak dapat menulisnya kembali ke Datastore.

Proyeksi dan properti multi-nilai

Memproyeksikan properti dengan beberapa nilai tidak akan mengisi semua nilai untuk properti tersebut. Sebagai gantinya, entity terpisah akan ditampilkan untuk setiap kombinasi unik dari nilai proyeksi yang cocok dengan kueri. Misalnya, Anda memiliki entity jenis Foo dengan dua properti multi-nilai, yaitu A dan B:

entity = Foo(A=[1, 1, 2, 3], B=['x', 'y', 'x'])

Kemudian, kueri proyeksi

SELECT A, B FROM Foo WHERE A < 3

akan menampilkan empat entity dengan kombinasi nilai berikut:

A = 1, B = 'x'
A = 1, B = 'y'
A = 2, B = 'x'
A = 2, B = 'y'

Perhatikan bahwa jika suatu entity memiliki properti multi-nilai tanpa nilai, tidak ada entri yang akan disertakan dalam indeks, dan tidak ada hasil untuk entity tersebut yang akan ditampilkan dari kueri proyeksi yang menyertakan properti tersebut.

Indeks untuk proyeksi

Kueri proyeksi mengharuskan semua properti yang ditentukan dalam proyeksi untuk disertakan dalam indeks Datastore. Server pengembangan App Engine secara otomatis menghasilkan indeks yang diperlukan untuk Anda di file konfigurasi indeks, index.yaml, yang diupload dengan aplikasi Anda.

Salah satu cara untuk meminimalkan jumlah indeks yang diperlukan adalah dengan memproyeksikan properti yang sama secara konsisten, meskipun tidak semuanya selalu diperlukan. Misalnya, kueri ini memerlukan dua indeks terpisah:

SELECT A, B FROM Kind
SELECT A, B, C FROM Kind

Namun, jika Anda selalu memproyeksikan properti A, B, dan C, meskipun C tidak diperlukan, hanya satu indeks yang akan diperlukan.

Mengonversi kueri yang ada menjadi kueri proyeksi mungkin memerlukan pembuatan indeks baru jika properti dalam proyeksi belum disertakan pada bagian kueri yang lain. Sebagai contoh, misalnya Anda memiliki kueri yang ada seperti

SELECT * FROM Kind WHERE A > 1 ORDER BY A, B

yang memerlukan indeks

Index(Kind, A, B)

Mengonversi ini ke salah satu kueri proyeksi

SELECT C FROM Kind WHERE A > 1 ORDER BY A, B
SELECT A, B, C FROM Kind WHERE A > 1 ORDER BY A, B

memperkenalkan properti baru (C) sehingga akan memerlukan pembuatan indeks baru Index(Kind, A, B, C). Perhatikan bahwa kueri proyeksi

SELECT A, B FROM Kind WHERE A > 1 ORDER BY A, B

tidak akan mengubah indeks yang diperlukan, karena properti yang diproyeksikan, yaitu A dan B, sudah disertakan dalam kueri yang ada.