Aplikasi dapat menggunakan kueri untuk menelusuri Datastore untuk entity yang cocok dengan kriteria penelusuran tertentu yang disebut filter.
Ringkasan
Aplikasi dapat menggunakan kueri untuk menelusuri Datastore untuk entity yang cocok dengan kriteria penelusuran tertentu yang disebut filter. Misalnya, aplikasi yang melacak beberapa buku tamu dapat menggunakan kueri untuk mengambil pesan dari satu buku tamu, yang diurutkan berdasarkan tanggal:
...
...
Beberapa kueri lebih kompleks daripada yang lain; datastore memerlukan indeks
pre-built untuk ini.
Indeks yang telah di-build ini ditetapkan dalam file konfigurasi, index.yaml
.
Di server pengembangan, jika Anda menjalankan kueri yang membutuhkan indeks yang belum Anda tentukan, server pengembangan akan otomatis menambahkannya ke index.yaml
.
Namun, di situs Anda, kueri yang membutuhkan indeks dan belum ditentukan akan gagal.
Dengan demikian, siklus pengembangan umumnya adalah mencoba kueri baru di server
pengembangan, lalu mengupdate situs agar menggunakan index.yaml
yang berubah secara otomatis.
Anda dapat mengupdate index.yaml
secara terpisah dari mengupload
aplikasi dengan menjalankan
gcloud app deploy index.yaml
.
Jika datastore Anda memiliki banyak entity, perlu waktu lama untuk membuat indeks baru untuk entity tersebut. Dalam hal ini, sebaiknya perbarui definisi indeks sebelum mengupload kode yang menggunakan indeks baru.
Anda dapat menggunakan Konsol Admin untuk mencari tahu kapan indeks selesai dibangun.
App Engine Datastore secara native mendukung filter untuk pencocokan persis (operator ==) dan perbandingan (operator <, <=, >, dan >=).
Solusi ini mendukung penggabungan beberapa filter menggunakan operasi
AND
Boolean, dengan beberapa batasan (lihat di bawah).
Selain operator native, API juga mendukung operator !=
, yang menggabungkan grup filter menggunakan operasi OR
Boolean, dan operasi IN
,
yang menguji kesetaraan dengan salah satu daftar kemungkinan nilai (seperti operator 'in' Python).
Operasi ini tidak memetakan 1:1 ke operasi native Datastore; jadi relatif sedikit unik dan lambat.
Pengujian ini diimplementasikan menggunakan penggabungan aliran hasil dalam memori. Perhatikan bahwa p != v
diimplementasikan sebagai "p < v OR p > v".
(Hal ini penting untuk properti berulang.)
Keterbatasan: Datastore menerapkan beberapa batasan pada kueri. Melanggar hal ini akan menyebabkan pengecualian. Misalnya, menggabungkan terlalu banyak filter, menggunakan ketidaksetaraan untuk beberapa properti, atau menggabungkan ketidaksetaraan dengan tata urutan di properti yang berbeda saat ini tidak diizinkan. Selain itu, filter yang merujuk ke beberapa properti terkadang memerlukan indeks sekunder untuk dikonfigurasi.
Tidak didukung: Datastore tidak secara langsung mendukung pencocokan substring, kecocokan yang tidak peka huruf besar/kecil, atau yang disebut penelusuran teks lengkap. Ada cara untuk menerapkan pencocokan yang tidak peka huruf besar/kecil dan bahkan penelusuran teks lengkap menggunakan properti terkomputasi.
Memfilter berdasarkan Nilai Properti
Ingat kembali class Account dari NDB Properties:
Biasanya, Anda tidak ingin mengambil semua entity dari jenis tertentu; Anda hanya menginginkan entity yang memiliki nilai atau rentang nilai tertentu untuk beberapa properti.
Objek properti membebani beberapa operator untuk menampilkan ekspresi filter yang dapat digunakan untuk mengontrol kueri: misalnya, untuk menemukan semua entity Akun yang properti userid-nya memiliki nilai persis 42, Anda dapat menggunakan ekspresi tersebut
(Jika Anda yakin hanya ada satu Account
dengan userid
tersebut, sebaiknya gunakan userid
sebagai kunci.
Account.get_by_id(...)
lebih cepat daripada Account.query(...).get()
.)
NDB mendukung operasi berikut:
property == value
property < value
property <= value
property > value
property >= value
property != value
property.IN([value1, value2])
Untuk memfilter ketidaksetaraan, Anda dapat menggunakan sintaksis seperti berikut:
Ini akan menemukan semua Entitas akun yang properti userid
-nya
lebih besar dari atau sama dengan 40.
Dua dari operasi ini, != dan IN , diterapkan sebagai kombinasi dari yang lain, dan sedikit unik seperti yang dijelaskan dalam != dan IN.
Anda dapat menentukan beberapa filter:
Fungsi ini menggabungkan argumen filter yang ditentukan, yang menampilkan semua entitas Akun yang nilai userid-nya lebih besar dari atau sama dengan 40 dan kurang dari 50.
Catatan: Seperti yang disebutkan sebelumnya, Datastore menolak kueri menggunakan pemfilteran ketidaksetaraan di lebih dari satu properti.
Daripada menetapkan seluruh filter kueri dalam satu ekspresi, Anda akan lebih mudah membuatnya dalam beberapa langkah: misalnya:
query3
setara dengan variabel query
dari contoh sebelumnya. Perhatikan bahwa objek kueri tidak dapat diubah, sehingga konstruksiquery2
tidak memengaruhiquery1
dan konstruksiquery3
tidak memengaruhi
query1
atau query2
.
Operasi != dan IN
Ingat kembali class Article dari NDB Properties:
Operasi !=
(tidak sama dengan) dan IN
(keanggotaan)
diterapkan dengan menggabungkan filter lain menggunakan
operasi OR
. Yang pertama,
property != value
diterapkan sebagai
(property < value) OR (property > value)
Misalnya,
setara dengan
Catatan:
Mungkin secara mengejutkan, kueri ini tidak menelusuri
entity Article
yang tidak menyertakan 'perl' sebagai tag.
Namun, metode ini akan menemukan semua entitas dengan sedikitnya satu tag yang tidak sama dengan 'perl'.
Misalnya, entity berikut akan disertakan dalam hasil, meskipun memiliki 'perl' sebagai salah satu tag-nya:
Namun, pertanyaan ini tidak akan disertakan:
Tidak ada cara untuk membuat kueri entity yang tidak menyertakan tag yang sama dengan 'perl'.
Demikian pula, operasi IN
property IN [value1, value2, ...]
yang menguji keanggotaan dalam daftar kemungkinan nilai, diimplementasikan sebagai
(property == value1) OR (property == value2) OR ...
Misalnya,
setara dengan
Catatan:
Kueri yang menggunakan OR
menghapus duplikat hasilnya: aliran hasil tidak
menyertakan entity lebih dari sekali, meskipun entity cocok dengan dua subkueri atau lebih.
Membuat Kueri untuk Properti Berulang
Class Article
yang ditentukan di bagian sebelumnya juga
berfungsi sebagai contoh pembuatan kueri untuk properti berulang. Khususnya, filter
seperti
akan menggunakan nilai tunggal, meskipun Article.tags
adalah properti berulang. Anda tidak dapat membandingkan properti berulang dengan objek daftar (Datastore tidak akan memahaminya), dan filter seperti
melakukan sesuatu yang
benar-benar berbeda dari menelusuri entity Article
yang nilai tag-nya adalah daftar
['python', 'ruby', 'php']
:
menelusuri entity yang nilai tags
(dianggap sebagai daftar)
berisiminimal satu dari nilai-nilai tersebut.
Kueri untuk nilai None
pada properti berulang memiliki perilaku yang tidak ditentukan; jangan lakukan itu.
Menggabungkan Operasi AND dan OR
Anda dapat membuat tingkat operasi AND
dan OR
secara acak.
Contoh:
Namun, karena penerapan OR
, kueri formulir ini yang terlalu kompleks mungkin gagal dengan pengecualian. Anda akan lebih aman jika menormalisasi filter ini, sehingga ada (maksimum) satu operasi OR
di bagian atas hierarki ekspresi, dan satu level operasi AND
di bawahnya.
Untuk melakukan normalisasi ini, Anda harus mengingat aturan logika Boolean Anda, serta bagaimana filter !=
dan IN
benar-benar diterapkan:
- Luaskan operator
!=
danIN
ke bentuk dasar, dengan!=
menjadi pemeriksaan untuk properti yang < atau > dari nilai tersebut, danIN
menjadi centang untuk properti yang menjadi == ke nilai pertama atau nilai kedua atau...sampai ke nilai terakhir dalam daftar. AND
denganOR
di dalamnya setara denganOR
dari beberapaAND
yang diterapkan ke varian asliAND
operand, dengan satuOR
operand yang menggantikanOR
asli. Misalnya,AND(a, b, OR(c, d))
setara denganOR(AND(a, b, c), AND(a, b, d))
AND
yang memiliki operand yang juga merupakan operasiAND
dapat menggabungkan operandAND
yang disusun bertingkat ke dalamAND
yang mencakupnya. Misalnya,AND(a, b, AND(c, d))
setara denganAND(a, b, c, d)
OR
yang memiliki operand yang juga merupakan operasiOR
dapat menggabungkan operandOR
yang disusun bertingkat ke dalamOR
yang mencakupnya. Misalnya,OR(a, b, OR(c, d))
setara denganOR(a, b, c, d)
Jika kami menerapkan transformasi ini secara bertahap pada filter contoh, menggunakan notasi yang lebih sederhana daripada Python, Anda akan mendapatkan:
- Menggunakan aturan #1 pada operator
IN
dan!=
:AND(tags == 'python', OR(tags == 'ruby', tags == 'jruby', AND(tags == 'php', OR(tags < 'perl', tags > 'perl'))))
- Menggunakan aturan #2 pada
OR
terdalam yang disusun bertingkat dalamAND
:AND(tags == 'python', OR(tags == 'ruby', tags == 'jruby', OR(AND(tags == 'php', tags < 'perl'), AND(tags == 'php', tags > 'perl'))))
- Menggunakan aturan #4 di
OR
yang disusun bertingkat dalamOR
lain:AND(tags == 'python', OR(tags == 'ruby', tags == 'jruby', AND(tags == 'php', tags < 'perl'), AND(tags == 'php', tags > 'perl')))
- Menggunakan aturan #2 pada
OR
lain yang disusun bertingkat dalamAND
:OR(AND(tags == 'python', tags == 'ruby'), AND(tags == 'python', tags == 'jruby'), AND(tags == 'python', AND(tags == 'php', tags < 'perl')), AND(tags == 'python', AND(tags == 'php', tags > 'perl')))
- Menggunakan aturan #3 untuk menciutkan
AND
lain yang disusun bertingkat:OR(AND(tags == 'python', tags == 'ruby'), AND(tags == 'python', tags == 'jruby'), AND(tags == 'python', tags == 'php', tags < 'perl'), AND(tags == 'python', tags == 'php', tags > 'perl'))
Perhatian:
Untuk beberapa filter, normalisasi ini dapat menyebabkan ledakan
kombinatorial. Pertimbangkan AND
dari 3 klausa OR
dengan masing-masing 2 klausa dasar.
Saat dinormalisasi, ini menjadi OR
dari 8 klausa AND
dengan masing-masing 3 klausa dasar: yaitu, 6 istilah menjadi 24.
Menentukan Tata Urutan
Anda dapat menggunakan metode order()
untuk menentukan urutan kueri yang menampilkan hasilnya. Metode ini mengambil daftar argumen, yang masing-masing merupakan objek properti (akan diurutkan dalam urutan menaik) atau negasinya (yang menunjukkan urutan menurun). Contoh:
Tindakan ini akan mengambil semua entity Greeting
, yang diurutkan berdasarkan nilai properti content
menaik.
Runutan entity yang berurutan dengan properti konten yang sama akan diurutkan berdasarkan nilai menurun dari properti date
-nya.
Anda dapat menggunakan beberapa panggilan order()
untuk efek yang sama:
Catatan: Saat menggabungkan filter dengan order()
, Datastore menolak kombinasi tertentu.
Secara khusus, saat Anda menggunakan filter ketidaksetaraan, tata urutan pertama (jika ada) harus menentukan properti yang sama dengan filter.
Selain itu, terkadang Anda perlu mengonfigurasi indeks sekunder.
Kueri Ancestor
Dengan kueri ancestor, Anda dapat membuat kueri yang sangat konsisten ke datastore, tetapi entity dengan ancestor yang sama dibatasi hingga 1 penulisan per detik. Berikut adalah perbandingan sederhana antara kueri ancestor dan non-ancestor yang dapat disesuaikan dengan pelanggan dan pembelian terkaitnya di datastore.
Pada contoh non-ancestor berikut, ada satu entity di datastore untuk setiap Customer
, dan satu entity di datastore untuk setiap Purchase
, dengan KeyProperty
yang mengarah ke pelanggan.
Untuk menemukan semua pembelian milik pelanggan, Anda dapat menggunakan kueri berikut:
Dalam hal ini, datastore menawarkan throughput tulis yang tinggi, tetapi hanya konsistensi tertunda. Jika pembelian baru ditambahkan, Anda mungkin mendapatkan data yang sudah tidak berlaku. Anda dapat menghilangkan perilaku ini menggunakan kueri ancestor.
Untuk pelanggan dan pembelian dengan kueri ancestor, Anda masih memiliki struktur yang sama dengan
dua entity terpisah. Bagian pelanggan sama. Namun, saat melakukan pembelian, Anda tidak perlu lagi menentukan KeyProperty()
untuk pembelian. Ini dikarenakan ketika menggunakan kueri ancestor, Anda memanggil kunci entity pelanggan saat membuat entity pembelian.
Setiap pembelian memiliki kunci, dan pelanggan juga memiliki kuncinya sendiri. Namun, setiap kunci pembelian akan memiliki kunci customer_entity yang disematkan di dalamnya. Ingat, ini akan dibatasi ke satu penulisan per ancestor per detik. Kode berikut akan membuat entity dengan ancestor:
Untuk membuat kueri pembelian pelanggan tertentu, gunakan kueri berikut.
Atribut Kueri
Objek kueri memiliki atribut data hanya baca berikut:
Atribut | Jenis | Default | Deskripsi |
---|---|---|---|
kind | str | None | Nama jenis (biasanya nama class) |
ancestor | Key | None | Ancestor ditentukan ke kueri |
filter | FilterNode | None | Ekspresi filter |
pesanan | Order | None | Tata urutan |
Mencetak objek kueri (atau memanggil str()
atau repr()
di dalamnya)
menghasilkan representasi string yang diformat dengan baik:
Pemfilteran untuk Nilai Properti Terstruktur
Kueri dapat langsung memfilter nilai kolom properti terstruktur.
Misalnya, kueri untuk semua kontak dengan alamat yang kotanya adalah
'Amsterdam'
akan terlihat seperti ini
Jika Anda menggabungkan beberapa filter, filter tersebut mungkin cocok dengan
sub-entity Address
yang berbeda dalam
entity Kontak yang sama.
Contoh:
dapat menemukan kontak dengan alamat yang kotanya adalah
'Amsterdam'
dan alamat lain (yang berbeda) yang jalannya adalah
'Spear St'
. Namun, setidaknya untuk filter kesetaraan, Anda dapat membuat kueri yang hanya menampilkan hasil dengan beberapa nilai dalam satu sub-entity:
Jika Anda menggunakan teknik ini, properti sub-entity yang sama dengan None
akan diabaikan dalam kueri.
Jika properti memiliki nilai default, Anda harus secara eksplisit menetapkannya ke
None
untuk mengabaikannya dalam kueri. Jika tidak, kueri akan menyertakan
filter yang mengharuskan nilai properti tersebut sama dengan default.
Misalnya, jika model Address
memiliki properti
country
dengan default='us'
, contoh
di atas hanya akan menampilkan kontak dengan negara yang sama dengan
'us'
; untuk mempertimbangkan kontak dengan nilai negara lain,
Anda harus memfilter
Address(city='San Francisco', street='Spear St',
country=None)
.
Jika sub-entity memiliki nilai properti yang sama dengan None
, nilai tersebut akan diabaikan. Oleh karena itu, tidak masuk akal untuk memfilter
nilai properti sub-entity None
.
Menggunakan Properti yang Dinamai berdasarkan String
Terkadang, Anda ingin memfilter atau mengurutkan kueri berdasarkan properti yang namanya ditentukan string. Misalnya, jika Anda membiarkan pengguna memasukkan kueri penelusuran
seperti tags:python
, akan lebih mudah untuk mengubahnya
menjadi kueri seperti
Article.query(Article."tags" == "python") # does NOT work
Jika model Anda adalah
Expando
, maka
filter dapat menggunakan GenericProperty
, class Expando
yang digunakan untuk properti dinamis:
MenggunakanGenericProperty
juga berfungsi jika model Anda bukan
Expando
, tetapi jika ingin memastikan bahwa Anda
hanya menggunakan nama properti yang ditentukan, Anda juga dapat menggunakan
atribut class _properties
atau gunakan getattr()
untuk mendapatkannya dari class:
Perbedaannya adalah getattr()
menggunakan "nama Python" properti, sementara _properties
diindeks oleh "nama datastore" properti. Ini hanya berbeda ketika properti
dideklarasikan dengan sesuatu seperti
Di sini, nama Python adalah title
, tetapi nama datastore adalah
t
.
Pendekatan ini juga berfungsi untuk mengurutkan hasil kueri:
Iterator Kueri
Saat kueri sedang berlangsung, statusnya disimpan di objek iterator. (Sebagian besar aplikasi tidak akan menggunakannya secara langsung; biasanya lebih mudah memanggil fetch(20)
daripada memanipulasi objek iterator.)
Ada dua cara dasar untuk mendapatkan objek tersebut:
- menggunakan fungsi
iter()
bawaan Python pada objekQuery
- memanggil metode
iter()
objekQuery
Yang pertama mendukung penggunaan loop for
Python (yang secara implisit memanggil fungsi iter()
) untuk melakukan loop atas suatu kueri.
Cara kedua, yang menggunakan metode iter()
objek Query
, memungkinkan Anda meneruskan opsi ke iterator untuk memengaruhi perilakunya. Misalnya, untuk menggunakan kueri khusus kunci dalam loop for
, Anda dapat menulis ini:
Iterator kueri memiliki metode lain yang berguna:
Metode | Deskripsi |
---|---|
__iter__()
| Bagian dari protokol iterator Python. |
next()
| Menampilkan hasil berikutnya atau menaikkan pengecualian StopIteration jika tidak ada. |
has_next()
| Menampilkan True jika panggilan next() berikutnya akan menampilkan hasil, False jika akan memunculkan StopIteration .Memblokir hingga jawaban atas pertanyaan ini diketahui dan mem-buffer hasilnya (jika ada) hingga Anda mengambilnya dengan next() .
|
probably_has_next()
| Seperti has_next() , tetapi menggunakan pintasan
yang lebih cepat (dan terkadang tidak akurat).Dapat menampilkan positif palsu (PP) ( True kapan
next() akan meningkatkan StopIteration ),
tetapi tidak akan pernah negatif palsu (NP) (False kapan
next() benar-benar akan memberikan hasil).
|
cursor_before()
| Menampilkan query cursor yang merepresentasikan titik tepat sebelum hasil terakhir yang ditampilkan. Menimbulkan pengecualian jika tidak ada kursor yang tersedia (khususnya, jika opsi kueri produce_cursors tidak diteruskan).
|
cursor_after()
| Menampilkan query cursor yang merepresentasikan titik tepat setelah hasil terakhir yang ditampilkan. Menimbulkan pengecualian jika tidak ada kursor yang tersedia (khususnya, jika opsi kueri produce_cursors tidak diteruskan).
|
index_list()
| Menampilkan daftar indeks yang digunakan oleh kueri yang dieksekusi, termasuk indeks properti utama, komposit, jenis, dan properti tunggal. |
Query Cursor
Query cursor adalah struktur data buram kecil yang mewakili titik kelanjutan dalam kueri. Ini berguna
untuk menampilkan halaman hasil satu per satu kepada pengguna; juga berguna untuk menangani tugas panjang
yang mungkin perlu dihentikan dan dilanjutkan.
Cara umum untuk menggunakannya adalah dengan metode fetch_page()
kueri.
Fungsi ini mirip dengan fetch()
, tetapi menampilkan (results, cursor, more)
tiga kali.
Flag more
yang ditampilkan menunjukkan bahwa mungkin ada lebih banyak hasil; UI dapat menggunakan ini, misalnya, untuk menyembunyikan
tombol atau link "Halaman Berikutnya".
Untuk meminta halaman berikutnya, teruskan kursor yang ditampilkan oleh satu
panggilan fetch_page()
ke panggilan berikutnya. BadArgumentError
ditampilkan jika Anda meneruskan kursor yang tidak valid. Perhatikan bahwa validasi hanya memeriksa apakah nilainya dienkode base64. Anda harus melakukan validasi lebih lanjut yang diperlukan.
Dengan demikian, agar pengguna dapat melihat semua entity yang cocok dengan kueri, mengambilnya satu per satu halaman, kode Anda mungkin terlihat seperti ini:
...
Perhatikan penggunaan urlsafe()
dan
Cursor(urlsafe=s)
untuk melakukan serialisasi dan
deserialisasi kursor.
Dengan cara ini, Anda dapat meneruskan kursor ke klien di web sebagai respons terhadap satu permintaan, dan menerimanya kembali dari klien dalam permintaan selanjutnya.
Catatan:
Metode fetch_page()
biasanya menampilkan kursor meskipun
tidak ada hasil lagi, tetapi hal ini tidak dijamin: nilai kursor
yang ditampilkan mungkin adalah None
. Perhatikan juga bahwa karena flag more
diimplementasikan menggunakan metode probably_has_next()
iterator, dalam situasi yang jarang terjadi, flag ini mungkin akan menampilkan True
meskipun halaman berikutnya kosong.
Beberapa kueri NDB tidak mendukung query cursor, tetapi Anda dapat memperbaikinya.
Jika kueri menggunakan IN
, OR
, atau !=
, maka hasil kueri tidak akan berfungsi dengan kursor kecuali diurutkan berdasarkan kunci.
Jika tidak mengurutkan hasil berdasarkan kunci dan memanggil
fetch_page()
, aplikasi akan mendapatkan BadArgumentError
.
Jika
User.query(User.name.IN(['Joe', 'Jane'])).order(User.name).fetch_page(N)
mengalami error, ubah menjadi
User.query(User.name.IN(['Joe', 'Jane'])).order(User.name, User.key).fetch_page(N)
Alih-alih "paging" pada hasil kueri, Anda dapat menggunakan metode
iter()
kueri untuk mendapatkan kursor pada titik yang tepat.
Untuk melakukannya, teruskan produce_cursors=True
ke iter()
; saat iterator berada di tempat yang tepat, panggil cursor_after()
untuk mendapatkan kursor yang muncul tepat setelahnya. (Atau, sama seperti, panggil cursor_before()
untuk kursor tepat sebelumnya.)
Perhatikan bahwa memanggil cursor_after()
atau cursor_before()
dapat membuat panggilan Datastore pemblokiran, yang menjalankan kembali bagian kueri untuk mengekstrak kursor yang menunjuk ke tengah batch.
Untuk menggunakan kursor ke halaman mundur melalui hasil kueri, buat kueri terbalik:
Memanggil Fungsi untuk setiap Entity ("Mapping")
Misalkan, Anda perlu mendapatkan entity Account
yang sesuai dengan entity Message
yang ditampilkan kueri.
Anda bisa menulis sesuatu seperti ini:
Namun, hal ini cukup tidak efisien: sistem menunggu untuk mengambil entity, lalu menggunakan entity tersebut; menunggu entity berikutnya, menggunakan entity tersebut. Ada banyak waktu tunggu. Cara lainnya adalah dengan menulis fungsi callback yang dipetakan di atas hasil kueri:
Versi ini akan berjalan agak lebih cepat daripada loop for
sederhana di atas karena beberapa konkurensi dapat terjadi.
Namun, karena panggilan get()
di
callback()
masih sinkron,
peningkatannya tidak begitu besar.
Ini adalah tempat yang baik untuk menggunakan
pengambilan asinkron.
GQL
GQL adalah bahasa yang mirip SQL untuk mengambil entity atau kunci dari App Engine Datastore. Meskipun fitur GQL berbeda dengan bahasa kueri untuk database relasional tradisional, sintaksis GQL mirip dengan SQL. Sintaksis GQL dijelaskan dalam Referensi GQL.
Anda dapat menggunakan GQL untuk membuat kueri. Cara ini mirip dengan membuat kueri dengan Model.query()
, tetapi menggunakan sintaksis GQL untuk menentukan filter dan urutan kueri. Untuk menggunakannya:
ndb.gql(querystring)
menampilkan objekQuery
(jenis sama dengan yang ditampilkan olehModel.query()
). Semua metode biasa tersedia pada objekQuery
tersebut:fetch()
,map_async()
,filter()
, dll.Model.gql(querystring)
adalah singkatan untukndb.gql("SELECT * FROM Model " + querystring)
. Biasanya, querystring terlihat seperti"WHERE prop1 > 0 AND prop2 = TRUE"
.- Untuk membuat kueri model yang berisi properti terstruktur, Anda dapat menggunakan
foo.bar
dalam sintaksis GQL untuk mereferensikan sub-properti. - GQL mendukung binding parameter seperti SQL. Aplikasi dapat menentukan
kueri, kemudian mengikat nilai ke dalamnya:
Memanggil fungsi
bind()
kueri akan menampilkan kueri baru; setelan ini tidak mengubah aslinya. - Jika class model Anda mengganti metode class
_get_kind()
, kueri GQL Anda harus menggunakan jenis yang ditampilkan fungsi tersebut, bukan nama class. - Jika properti dalam model Anda mengganti namanya (misalnya,
foo = StringProperty('bar')
) kueri GQL Anda harus menggunakan nama properti yang telah diganti (dalam contoh,bar
).
Selalu gunakan fitur parameter-binding jika beberapa nilai dalam kueri Anda adalah variabel yang disediakan pengguna. Hal ini menghindari serangan berdasarkan peretasan sintaksis.
Error terjadi saat membuat kueri untuk model yang belum diimpor (atau, secara lebih umum, ditentukan).
Error terjadi saat menggunakan nama properti yang tidak ditentukan oleh class model kecuali jika model tersebut adalah Luaskano.
Menentukan batas atau offset untuk fetch()
kueri akan menggantikan batas atau offset yang ditetapkan oleh klausa OFFSET
dan LIMIT
GQL. Jangan gabungkan OFFSET
dan LIMIT
GQL dengan fetch_page()
Perhatikan bahwa nilai maksimum 1.000 hasil yang diberlakukan oleh App Engine pada kueri berlaku untuk offset dan batas.
Jika Anda terbiasa dengan SQL, berhati-hatilah terhadap asumsi palsu saat menggunakan GQL. GQL diterjemahkan ke API kueri native NDB. Hal ini berbeda dengan mapper Object-Relational standar (seperti SQLAlchemy atau dukungan database Django), yang panggilan API-nya diterjemahkan ke dalam SQL sebelum dikirim ke server database. GQL tidak mendukung modifikasi Datastore (penyisipan, penghapusan, atau pembaruan); GQL hanya mendukung kueri.