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
Datastore menyediakan akses terprogram ke beberapa metadatanya untuk mendukung metaprogramming, menerapkan fungsi administratif backend, menyederhanakan caching yang konsisten, dan tujuan serupa; Anda dapat menggunakannya, misalnya, untuk membangun penampil Datastore kustom untuk aplikasi Anda. Metadata yang tersedia mencakup informasi tentang entity group, namespace, jenis entity, dan properti yang digunakan aplikasi Anda, serta representasi properti untuk setiap properti.
Dasbor Datastore di Konsol Google Cloud juga menyediakan beberapa metadata tentang aplikasi Anda, tetapi data yang ditampilkan di sana berbeda dalam beberapa hal penting dengan yang ditampilkan oleh fungsi-fungsi ini.
- Keaktualan. Membaca metadata menggunakan API akan mendapatkan data saat ini, sedangkan data di dasbor hanya diperbarui sekali sehari.
- Daftar Isi. Beberapa metadata di dasbor tidak tersedia melalui API; dan sebaliknya.
- Kecepatan. Aktivitas dan kueri Metadata ditagih dengan cara yang sama seperti aktivitas dan kueri Datastore. Kueri metadata yang mengambil informasi tentang namespace, jenis, dan properti umumnya lambat untuk dijalankan. Pada dasarnya, perkirakan bahwa kueri metadata yang menampilkan entity N akan memerlukan waktu yang sama seperti N kueri biasa yang masing-masing menampilkan satu entity. Selain itu, kueri representasi properti (kueri properti khusus non-kunci) lebih lambat dari kueri properti khusus kunci. Metadata yang diperoleh metadata entity group agak lebih cepat daripada mendapatkan entity reguler.
Fungsi bantuan
Fungsi berikut memperoleh informasi metadata:
get_entity_group_version()
mendapatkan nomor versi untuk entity group; hal ini berguna untuk mengetahui apakah ada entity dalam grup yang telah berubah sejak terakhir kali Anda mendapatkan nomor versi.get_namespaces()
menampilkan daftar yang berisi nama semua namespace aplikasi atau namespace yang berada dalam rentang yang ditentukan.get_kinds()
menampilkan daftar yang berisi nama semua jenis entity aplikasi atau jenis entity yang ada dalam rentang tertentu.get_properties_of_kind()
menampilkan daftar yang berisi nama semua properti terindeks aplikasi (atau properti yang berada dalam rentang tertentu) yang terkait dengan jenis entity tertentu. Properti yang tidak diindeks tidak disertakan.get_representations_of_kind()
menampilkan kamus yang berisi representasi untuk semua properti terindeks aplikasi atau properti dalam rentang tertentu yang terkait dengan jenis entity tertentu. Kamus memetakan nama setiap properti ke daftar representasi properti tersebut. Properti yang tidak diindeks tidak disertakan.
Metadata entity group
Cloud Datastore menyediakan akses ke "versi" entity group, angka yang benar-benar positif yang dijamin akan meningkat pada setiap perubahan pada entity group tersebut.
Contoh berikut menunjukkan cara mendapatkan versi entity group:
from google.appengine.ext import db
from google.appengine.ext.db import metadata
class Simple(db.Model):
x = db.IntegerProperty()
entity1 = Simple(x=11)
entity1.put()
# Print entity1's entity group version
print 'version', metadata.get_entity_group_version(entity1)
# Write to a different entity group
entity2 = Simple(x=22)
entity2.put()
# Will print the same version, as entity1's entity group has not changed
print 'version', metadata.get_entity_group_version(entity1)
# Change entity1's entity group by adding a new child entity
entity3 = Simple(x=33, parent=entity1.key())
entity3.put()
# Will print a higher version, as entity1's entity group has changed
print metadata.get_entity_group_version(entity1)
Perilaku lama
Dalam perilaku versi entity group lama, versi entity group hanya meningkat saat terjadi perubahan pada entity group. Perilaku metadata entity group lama dapat digunakan, misalnya, untuk menjaga cache yang konsisten dari kueri ancestor yang kompleks di suatu entity group.
Contoh ini menyimpan hasil kueri ke dalam cache (jumlah hasil yang cocok) dan menggunakan perilaku lama versi entity group untuk menggunakan nilai yang di-cache jika nilai tersebut terbaru:
from google.appengine.api import memcache
from google.appengine.ext import db
from google.appengine.ext.db import metadata
def count_entity_group(entity_group_key):
"""Count the entities in the specified entity group."""
# Check if we have a cached version of the current entity group count
cached = memcache.get(str(entity_group_key))
if cached:
(version, count) = cached
# Is the cached value for the current version?
if version == metadata.get_entity_group_version(entity_group_key):
return count
def tx():
# Need to actually count entities. Using a transaction to get a consistent
# count and entity group version.
count = db.Query(keys_only=True).ancestor(entity_group_key).count(limit=5000)
# Cache the count and the entity group version
version = metadata.get_entity_group_version(entity_group_key)
memcache.set(str(entity_group_key), (version, count))
return count
return db.run_in_transaction(tx)
get_entity_group_version()
dapat menampilkan None
untuk entity group yang belum pernah ditulis.
Versi entity group diperoleh dengan memanggil get()
pada entity pseudo khusus
yang berisi properti __version__
. Lihat dokumentasi referensi tentang
EntityGroup untuk detailnya.
Kueri metadata
Jika fungsi bantuan yang dijelaskan di bagian sebelumnya tidak memenuhi kebutuhan, Anda dapat mengeluarkan permintaan metadata yang lebih mendetail atau fleksibel dengan kueri metadata eksplisit. Di Python, class model untuk kueri semacam itu
ditentukan dalam
paket
google.appengine.ext.db.metadata
. Model ini menyediakan jenis entity khusus yang dicadangkan untuk kueri metadata:
Class model | Jenis entity |
---|---|
Namespace |
__namespace__ |
Kind |
__kind__ |
Property |
__property__ |
Model dan jenis ini tidak akan bertentangan dengan model dan jenis lain dengan nama yang sama yang mungkin sudah ada di aplikasi Anda. Dengan membuat kueri jenis khusus ini, Anda dapat mengambil entity yang berisi metadata yang diinginkan.
Entity yang ditampilkan oleh kueri metadata dibuat secara dinamis, berdasarkan status Datastore saat ini. Meskipun Anda dapat
membuat instance lokal dari class model Namespace
.Kind
, atauProperty
, setiap upaya untuk menyimpannya di Datastore akan gagal dengan pengecualian BadRequestError
.
Anda dapat menerbitkan kueri metadata menggunakan objek kueri yang termasuk dalam salah satu dari dua class:
- Objek
Query
yang ditampilkan oleh metode classNamespace.all()
,Kind.all()
, atauProperty.all()
(diwarisi dari metode superclassModel.all()
) - Objek
GqlQuery
untuk kueri bergaya GQL
Contoh berikut menampilkan nama semua jenis entity dalam aplikasi:
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Kind
for k in Kind.all():
print "kind: '%s'" % k.kind_name
Kueri namespace
Jika aplikasi Anda menggunakan Namespaces API, Anda dapat menggunakan kueri namespace untuk menemukan semua namespace yang digunakan dalam entity aplikasi. Dengan begitu, Anda dapat melakukan aktivitas seperti fungsi administratif di beberapa namespace.
Kueri namespace menampilkan entity __namespace__
jenis khusus yang nama kuncinya adalah nama namespace. (Pengecualiannya adalah namespace default
yang ditetapkan oleh string kosong ""
: karena string kosong bukan nama kunci
yang valid, namespace ini dikunci dengan ID numerik 1
.) Kueri jenis ini hanya mendukung pemfilteran untuk rentang pada properti pseudo khusus __key__
, yang nilainya adalah kunci entity. Hasilnya dapat diurutkan berdasarkan nilai __key__
menaik (tetapi tidak menurun). Karena entity __namespace__
tidak memiliki properti, kueri khusus kunci dan non-kunci menampilkan informasi
yang sama.
Entity namespace adalah instance class model google.appengine.ext.db.metadata.Namespace
. Properti string
namespace_name
,
yang dihitung dari kunci entity, menampilkan nama namespace yang sesuai.
(Jika kunci memiliki ID numerik 1
, properti akan menampilkan string kosong.) Untuk
memfasilitasi pembuatan kueri, model Namespace
menyediakan metode class berikut:
Namespace.key_for_namespace()
membuat kunci__namespace__
dari nama namespace.Namespace.key_to_namespace()
menampilkan nama namespace yang sesuai dengan kunci__namespace__
yang ditentukan.
Sebagai contoh, berikut adalah penerapan fungsi bantuan
get_namespaces()
, yang menampilkan daftar berisi nama semua namespace aplikasi (atau namespace yang berada dalam rentang antara dua nama yang ditentukan, start
dan padaend
):
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Namespace
def get_namespaces(start=None, end=None):
# Start with unrestricted namespace query
q = Namespace.all()
# Limit to specified range, if any
if start is not None:
q.filter('__key__ >=', Namespace.key_for_namespace(start))
if end is not None:
q.filter('__key__ <', Namespace.key_for_namespace(end))
# Return list of query results
return [ns.namespace_name for ns in q]
Kueri jenis
Kueri jenis menampilkan entity jenis __kind__
yang nama kuncinya adalah nama
jenis entity. Kueri jenis ini secara implisit dibatasi untuk namespace saat ini
dan hanya mendukung pemfilteran untuk rentang melalui
properti pseudo __key__
. Hasilnya dapat diurutkan berdasarkan nilai __key__
menaik (tetapi tidak menurun). Karena entity __kind__
tidak memiliki properti, kueri khusus kunci dan non-kunci menampilkan informasi yang sama.
Entity jenis adalah instance dari class model google.appengine.ext.db.metadata.Kind
.
Properti string kind_name
,
yang dihitung dari kunci entity, menampilkan nama jenis entity
yang sesuai. Untuk memfasilitasi pembuatan kueri, model Kind
menyediakan metode class
berikut:
Kind.key_for_kind()
membuat kunci__kind__
dari nama jenis.Kind.key_to_kind()
menampilkan nama jenis yang sesuai dengan kunci__kind__
yang ditentukan.
Sebagai contoh, berikut adalah penerapan fungsi bantuan
get_kinds()
, yang menampilkan daftar berisi nama semua jenis entity aplikasi (atau yang berada dalam rentang antara dua nama yang ditentukan, start
dan padaend
):
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Kind
def get_kinds(start=None, end=None):
# Start with unrestricted kind query
q = Kind.all()
# Limit to specified range, if any
if start is not None and start != '':
q.filter('__key__ >=', Kind.key_for_kind(start))
if end is not None:
if end == '':
return [] # Empty string is not a valid kind name, so can't filter
q.filter('__key__ <', Kind.key_for_kind(end))
# Return list of query results
return [k.kind_name for k in q]
Contoh berikut mencetak semua jenis yang namanya diawali dengan huruf kecil:
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Kind
# Start with unrestricted kind query
q = Kind.all()
# Limit to lowercase initial letters
q.filter('__key__ >=', Kind.key_for_kind('a'))
endChar = chr(ord('z') + 1) # Character after 'z'
q.filter('__key__ <', Kind.key_for_kind(endChar))
# Print query results
for k in q:
print k.kind_name
Kueri properti
Kueri properti menampilkan entity jenis __property__
yang menunjukkan
properti yang terkait dengan jenis entity (terlepas dari apakah
properti tersebut saat ini ditentukan dalam model jenis atau tidak). Entity yang mewakili properti P jenis K dibuat sebagai berikut:
- Kunci entity memiliki jenis
__property__
dan nama kunci P. - Kunci parent entity memiliki jenis
__kind__
dan nama kunci K.
Entity properti adalah instance dari class model
google.appengine.ext.db.metadata.Property
. Properti string
kind_name
dan property_name
,
yang dihitung dari kunci entity, menampilkan nama jenis dan properti yang sesuai. Model Property
menyediakan empat metode class untuk menyederhanakan pembuatan
dan pemeriksaan kunci __property__
:
Property.key_for_kind()
membuat kunci__kind__
induk untuk kunci__property__
dari jenis entity tertentu.Property.key_for_property()
membuat kunci__property__
untuk jenis dan properti yang ditentukan.Property.key_to_kind()
menampilkan nama jenis yang terkait dengan kunci__property__
.Property.key_to_property()
menampilkan nama properti yang terkait dengan kunci__property__
(atauNone
jika kunci tersebut hanya menentukan jenis).
Contoh berikut mengilustrasikan metode ini:
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Property
class Employee(db.Model):
name = db.StringProperty()
ssn = db.IntegerProperty()
employee_key = Property.key_for_kind("Employee")
employee_name_key = Property.key_for_property("Employee", "Name")
Property.key_to_kind(employee_key) # Returns "Employee"
Property.key_to_property(employee_name_key) # Returns "Name"
Perilaku kueri properti bergantung pada apakah kueri tersebut keys-only atau khusus non-kunci (representasi properti), seperti yang dijelaskan di subbagian di bawah.
Kueri properti: khusus kunci
Kueri properti khusus kunci menampilkan kunci untuk setiap properti terindeks dari jenis entity yang ditentukan. (Properti yang tidak diindeks tidak disertakan.) Contoh berikut mencetak nama semua jenis entity aplikasi dan properti yang terkait dengan masing-masing jenis entity tersebut:
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Property
# Create unrestricted keys-only property query
q = Property.all(keys_only=True)
# Print query results
for p in q:
print "%s: %s" % (Property.key_to_kind(p), Property.key_to_property(p))
Kueri jenis ini secara implisit dibatasi untuk namespace saat ini dan
mendukung pemfilteran hanya untuk rentang melalui properti pseudo __key__
, dengan
kunci menunjukkan entity __kind__
atau __property__
. Hasilnya dapat diurutkan berdasarkan nilai __key__
menaik (tetapi tidak menurun). Pemfilteran diterapkan pada pasangan jenis properti, yang diurutkan pertama berdasarkan jenis dan kedua berdasarkan properti: misalnya, Anda memiliki entity dengan properti berikut:
- jenis
Account
dengan propertibalance
company
- jenis
Employee
dengan propertiname
ssn
- jenis
Invoice
dengan propertidate
amount
- jenis
Manager
dengan propertiname
title
- jenis
Product
dengan propertidescription
price
Kueri untuk menampilkan data properti akan terlihat seperti ini:
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Property
# Start with unrestricted keys-only property query
q = Property.all(keys_only=True)
# Limit range
q.filter('__key__ >=', Property.key_for_property("Employee", "salary"))
q.filter('__key__ <=', Property.key_for_property("Manager", "salary"))
# Print query results
for p in q:
print "%s: %s" % (Property.key_to_kind(p), Property.key_to_property(p))
Kueri di atas akan menampilkan hal berikut:
Employee: ssn
Invoice: date
Invoice: amount
Manager: name
Perhatikan bahwa hasilnya tidak menyertakan properti name
dari jenis Employee
dan properti title
dari jenis Manager
, maupun properti apa pun dengan jenis
Account
dan Product
, karena berada di luar rentang yang ditetapkan untuk kueri ini.
Kueri properti juga mendukung pemfilteran ancestor pada kunci __kind__
atau __property__
, untuk membatasi hasil kueri ke satu jenis atau properti. Anda
dapat menggunakannya, misalnya, untuk mendapatkan properti yang terkait dengan jenis
entity tertentu, seperti dalam contoh berikut:
get_properties_of_kind()
)
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Property
def get_properties_of_kind(kind, start=None, end=None):
# Start with unrestricted keys-only property query
q = Property.all(keys_only=True)
# Limit to specified kind
q.ancestor(Property.key_for_kind(kind))
# Limit to specified range, if any
if start is not None and start != '':
q.filter('__key__ >=', Property.key_for_property(kind, start))
if end is not None:
if end == '':
return [] # Empty string is not a valid property name, so can't filter
q.filter('__key__ <', Property.key_for_property(kind, end))
# Return list of query results
return [Property.key_to_property(p) for p in q]
Kueri properti: khusus non-kunci (representasi properti)
Kueri properti khusus non-kunci, yang dikenal sebagai kueri representasi properti, menampilkan informasi tambahan tentang representasi yang digunakan oleh setiap pasangan jenis properti. (Properti yang tidak diindeks tidak disertakan.) Entity yang ditampilkan untuk properti
P sejenis K memiliki kunci yang sama dengan
kueri khusus kunci terkait, serta properti property_representation
tambahan yang menampilkan
representasi properti. Nilai properti ini adalah class instance StringListProperty
yang berisi satu string untuk setiap representasi properti P yang ditemukan dalam entity jenis K.
Perhatikan bahwa representasi tidak sama dengan class properti; beberapa class properti dapat dipetakan ke representasi yang sama. (Misalnya,
StringProperty
dan
PhoneNumberProperty
sama-sama menggunakan representasi STRING
.)
Tabel berikut dipetakan dari class properti ke representasinya:
Class properti | Representasi |
---|---|
IntegerProperty |
INT64 |
FloatProperty |
DOUBLE |
BooleanProperty |
BOOLEAN |
StringProperty |
STRING |
ByteStringProperty |
STRING |
DateProperty |
INT64 |
TimeProperty |
INT64 |
DateTimeProperty |
INT64 |
GeoPtProperty |
POINT |
PostalAddressProperty |
STRING |
PhoneNumberProperty |
STRING |
EmailProperty |
STRING |
UserProperty |
USER |
IMProperty |
STRING |
LinkProperty |
STRING |
CategoryProperty |
STRING |
RatingProperty |
INT64 |
ReferenceProperty SelfReferenceProperty |
REFERENCE |
blobstore.BlobReferenceProperty |
STRING |
ListProperty |
Representasi elemen daftar |
StringListProperty |
Representasi elemen daftar |
Sebagai contoh, berikut adalah penerapan fungsi bantuan get_representations_of_kind()
, yang menampilkan kamus yang berisi representasi untuk semua properti yang diindeks oleh aplikasi (atau properti tersebut dalam rentang antara dua nama yang ditentukan, start
dan end
) yang terkait dengan jenis entity tertentu. Kamus
memetakan nama setiap properti ke daftar representasi properti tersebut:
from google.appengine.ext import db
from google.appengine.ext.db.metadata import Property
def get_representations_of_kind(kind, start=None, end=None):
# Start with unrestricted non-keys-only property query
q = Property.all()
# Limit to specified kind
q.ancestor(Property.key_for_kind(kind))
# Limit to specified range, if any
if start is not None and start != '':
q.filter('__key__ >=', Property.key_for_property(kind, start))
if end is not None:
if end == '':
return [] # Empty string is not a valid property name, so can't filter
q.filter('__key__ <', Property.key_for_property(kind, end))
# Initialize result dictionary
result = {}
# Add query results to dictionary
for p in q:
result[p.property_name] = p.property_representation
# Return dictionary
return result