Referensi Properti Entity

Firestore dalam mode Datastore (Datastore) mendukung berbagai jenis data untuk nilai properti. Hal ini mencakup, antara lain:

  • Bilangan bulat
  • Angka floating-point
  • String
  • Tanggal
  • Data biner

Untuk mengetahui daftar lengkap dari jenis, lihat Properti dan jenis nilai.

Jenis properti dan nilai

Nilai data yang terkait dengan entity terdiri dari satu atau beberapa properti. Setiap properti memiliki nama dan satu atau beberapa nilai. Properti dapat memiliki nilai yang berisi lebih dari satu jenis, dan dua entity dapat memiliki nilai dari jenis yang berbeda untuk properti yang sama. Properti dapat diindeks atau tidak diindeks (kueri yang mengurutkan atau memfilter pada properti P akan mengabaikan entity jika P tidak diindeks). Entity dapat memiliki maksimal 20.000 properti yang diindeks.

Jenis nilai berikut ini didukung:

Jika kueri melibatkan properti dengan nilai jenis campuran, Datastore akan menggunakan pengurutan deterministik berdasarkan representasi internal:

  1. Nilai null
  2. Angka fixed-point
    • Bilangan bulat
    • Tanggal dan waktu
  3. Nilai boolean
  4. Urutan byte
    • String Unicode
    • Kunci Blobstore
  5. Angka floating-point
  6. Kunci Datastore

Karena string teks panjang dan string byte panjang tidak diindeks, maka pengurutan tidak ditentukan.

Jenis Properti

NDB mendukung jenis properti berikut:

Jenis properti Deskripsi
IntegerProperty Bilangan bulat 64-bit yang telah ditandai.
FloatProperty Bilangan floating point presisi ganda
BooleanProperty Boolean
StringProperty String unicode; hingga 1.500 byte, terindeks
TextProperty String unicode; panjang tidak terbatas, tidak terindeks
BlobProperty String byte yang tidak diinterpretasikan:
jika Anda menetapkan indexed=True, hingga 1.500 byte, terindeks;
jika indexed adalah False (default), panjang tidak terbatas, tidak terindeks.
Argumen kata kunci opsional: compressed.
DateTimeProperty Tanggal dan waktu (lihat Properti Tanggal dan Waktu)
DateProperty Tanggal (lihat Properti Tanggal dan Waktu)
TimeProperty Waktu (lihat Properti Tanggal dan Waktu)
GeoPtProperty Lokasi geografis. Ini adalah objek ndb.GeoPt. Objek ini memiliki atribut lat dan lon, keduanya merupakan float. Anda dapat membuat satu float dengan dua float seperti ndb.GeoPt(52.37, 4.88) atau dengan string ndb.GeoPt("52.37, 4.88"). (Ini sebenarnya class yang sama dengan db.GeoPt)
KeyProperty Kunci Datastore
Argumen kata kunci opsional: jenis=kind, untuk mengharuskan kunci yang ditetapkan ke properti ini selalu memiliki jenis yang ditunjukkan. Dapat berupa string atau subclass Model.
BlobKeyProperty Kunci Blobstore
Terkait dengan BlobReferenceProperty di db API lama, tetapi nilai propertinya adalah BlobKey, bukan BlobInfo; Anda dapat membuat BlobInfo darinya menggunakan BlobInfo(blobkey)
UserProperty Objek pengguna.
StructuredProperty Mencakup satu jenis model di dalam model lainnya, berdasarkan nilai (lihat Properti Terstruktur)
LocalStructuredProperty Seperti StructuredProperty, tetapi representasi pada disk adalah blob tersembunyui dan tidak terindeks (lihat Properti Terstruktur).
Argumen kata kunci opsional: compressed.
JsonProperty Nilai adalah objek Python (seperti daftar, dikte, atau string) yang dapat diserialisasi menggunakan modul json Python; Datastore menyimpan serialisasi JSON sebagai blob. Tidak terindeks secara default.
Argumen kata kunci opsional: compressed.
PickleProperty Nilai adalah objek Python (seperti daftar atau dikte atau string) yang dapat diserialisasi menggunakan protokol pickle Python; Datastore menyimpan serialisasi pickle sebagai blob. Tidak terindeks secara default.
Argumen kata kunci opsional: compressed.
GenericProperty Nilai umum
Sebagian besar digunakan oleh class Expando, tetapi juga dapat digunakan secara eksplisit. Jenisnya dapat berupa int, long, float, bool, str, unicode, datetime, Key, BlobKey, GeoPt, User, None.
ComputedProperty Nilai yang dihitung dari properti lain dengan fungsi yang ditentukan pengguna. (Lihat Properti Terhitung.)

Beberapa properti ini memiliki argumen kata kunci opsional, compressed. Jika properti memiliki compressed=True, datanya akan dikompresi dengan gzip di disk. Metode ini menggunakan lebih sedikit ruang, tetapi memerlukan CPU untuk mengenkode/mendekode pada operasi tulis dan baca.

Kompresi dan dekompresi bersifat "lambat"; nilai properti terkompresi hanya akan didekompresi saat pertama kali Anda mengaksesnya. Jika Anda membaca entity yang berisi nilai properti terkompresi dan menulisnya kembali tanpa mengakses properti terkompresi, entity tersebut tidak akan didekompresi dan dikompresi sama sekali. Cache dalam konteks juga berpartisipasi dalam skema lambat ini, tetapi memcache selalu menyimpan nilai terkompresi untuk properti terkompresi.

Karena banyaknya waktu CPU yang diperlukan untuk kompresi, sebaiknya gunakan properti terkompresi hanya jika data terlalu besar untuk muat tanpanya. Perlu diingat bahwa kompresi berbasis gzip biasanya tidak efektif untuk gambar dan data media lainnya, karena format tersebut sudah dikompresi menggunakan algoritme kompresi khusus media (mis., JPEG untuk gambar).

Opsi Properti

Sebagian besar jenis properti mendukung beberapa argumen standar. Yang pertama adalah argumen posisi opsional yang menentukan nama Datastore properti. Anda dapat menggunakannya untuk memberi nama properti yang berbeda di Datastore dari sudut pandang aplikasi. Penggunaan umum untuk hal ini adalah mengurangi ruang di Datastore, sehingga Datastore dapat menggunakan nama properti yang disingkat, sementara kode Anda menggunakan nama yang lebih panjang dan lebih bermakna. Misalnya,

class Employee(ndb.Model):
    full_name = ndb.StringProperty('n')
    retirement_age = ndb.IntegerProperty('r')

Hal ini sangat berguna untuk properti berulang yang diperkirakan memiliki banyak nilai per entity.

Selain itu, sebagian besar jenis properti mendukung argumen kata kunci berikut:

Argumen Jenis Default Deskripsi
indexed bool Biasanya True Menyertakan properti dalam indeks Datastore; jika False, nilai tidak dapat dikueri, tetapi penulisan akan lebih cepat. Tidak semua jenis properti mendukung pengindeksan; penetapan indexed ke True akan gagal.
Properti yang tidak terindeks memerlukan operasi tulis yang lebih sedikit daripada properti yang terindeks.
repeated bool False Nilai properti adalah daftar Python yang berisi nilai dari jenis yang mendasarinya (lihat Properti Berulang).
Tidak dapat digabungkan dengan required=True atau default=True.
required bool False Properti harus memiliki nilai yang ditentukan.
default Jenis dasar properti Tidak ada Nilai default properti jika tidak ada yang ditentukan secara eksplisit.
choices Daftar nilai jenis dasar None Daftar opsional nilai yang diizinkan.
validator Fungsi None

Fungsi opsional untuk memvalidasi dan mungkin mengonversi nilai.

Akan disebut sebagai argumen (prop, value) dan harus menampilkan nilai (yang mungkin dikonversi) atau memunculkan pengecualian. Memanggil kembali fungsi pada nilai yang dikonversi tidak boleh mengubah nilai lebih lanjut. (Misalnya, menampilkan value.strip() atau value.lower() diperbolehkan, tetapi tidak untuk value + '$'.) Juga dapat menampilkan None, yang berarti "tidak ada perubahan". Lihat juga Menulis Subclass Properti

verbose_name string None

Label HTML opsional untuk digunakan dalam kerangka kerja formulir web seperti jinja2.

Properti Berulang

Setiap properti dengan repeated=True akan menjadi properti berulang. Properti ini mengambil daftar nilai dari jenis yang mendasarinya, bukan nilai tunggal. Misalnya, nilai properti yang ditentukan dengan IntegerProperty(repeated=True) adalah daftar bilangan bulat.

Datastore dapat melihat beberapa nilai untuk properti tersebut. Catatan indeks terpisah dibuat untuk setiap nilai. Hal ini memengaruhi semantik kueri; lihat Membuat Kueri untuk Properti Berulang sebagai contoh.

Contoh ini menggunakan properti berulang:

class Article(ndb.Model):
    title = ndb.StringProperty()
    stars = ndb.IntegerProperty()
    tags = ndb.StringProperty(repeated=True)
...
article = Article(
    title='Python versus Ruby',
    stars=3,
    tags=['python', 'ruby'])
article.put()

Tindakan ini akan membuat entity Datastore dengan konten berikut:

assert article.title == 'Python versus Ruby'
assert article.stars == 3
assert sorted(article.tags) == sorted(['python', 'ruby'])

Saat membuat kueri untuk properti tags, entity ini akan memenuhi kueri untuk 'python' atau 'ruby'.

Saat memperbarui properti berulang, Anda dapat menetapkan daftar baru atau mengubah daftar yang ada. Saat Anda menetapkan daftar baru, jenis item daftar akan segera divalidasi. Jenis item yang tidak valid (misalnya, menetapkan [1, 2] ke art.tags di atas) akan menimbulkan pengecualian. Saat Anda mengubah daftar, perubahan tidak akan langsung divalidasi. Sebagai gantinya, nilai akan divalidasi saat Anda menulis entity ke Datastore.

Datastore mempertahankan urutan item daftar dalam properti berulang sehingga Anda dapat menetapkan beberapa makna pada urutannya.

Properti Tanggal dan Waktu

Tiga jenis properti tersedia untuk menyimpan nilai terkait tanggal dan waktu:

  • DateProperty
  • TimeProperty
  • DateTimeProperty

Ini mengambil nilai yang termasuk dalam class yang sesuai (date, time, datetime) dari modul datetime Python standar. Yang paling umum di antara ketiganya adalah DateTimeProperty yang menunjukkan tanggal kalender dan waktu; yang lainnya terkadang berguna untuk tujuan khusus yang hanya memerlukan tanggal (seperti tanggal lahir) atau hanya waktu (seperti waktu rapat). Karena alasan teknis, DateProperty dan TimeProperty adalah subclass DateTimeProperty, tetapi Anda tidak boleh bergantung pada hubungan pewarisan ini (dan perlu diperhatikan bahwa hubungan ini berbeda dengan hubungan pewarisan di antara class dasar yang ditentukan oleh modul datetime itu sendiri).

Catatan: Waktu jam App Engine selalu dinyatakan dalam waktu universal terkoordinasi (UTC). Hal ini menjadi relevan jika Anda menggunakan tanggal atau waktu saat ini (datetime.datetime.now()) sebagai nilai atau melakukan konversi antara objek datetime dan stempel waktu POSIX atau tupel waktu. Namun, tidak ada informasi zona waktu eksplisit yang disimpan di Datastore. Jadi, jika berhati-hati, Anda dapat menggunakannya untuk mewakili waktu lokal dalam zona waktu apa pun, jika Anda menggunakan waktu saat ini atau konversi.

Masing-masing properti ini memiliki dua opsi kata kunci Boolean tambahan:

Opsi Deskripsi
auto_now_add Tetapkan properti ke tanggal/waktu saat ini ketika entity dibuat. Anda dapat mengganti properti ini secara manual. Saat entity diperbarui, properti tidak berubah. Untuk perilaku tersebut, gunakan auto_now.
auto_now Tetapkan properti ke tanggal/waktu saat ini ketika entity dibuat dan setiap kali entitas diperbarui.

Opsi ini tidak dapat digabungkan dengan repeated=True. Keduanya ditetapkan secara default ke False; jika keduanya ditetapkan ke True, auto_now akan diprioritaskan. Anda dapat mengganti nilai untuk properti dengan auto_now_add=True, tetapi tidak untuk properti dengan auto_now=True. Nilai otomatis tidak dihasilkan hingga entity ditulis; artinya, opsi ini tidak memberikan default dinamis. (Detail ini berbeda dengan db API lama.)

Catatan: Jika transaksi yang menulis properti dengan auto_now_add=True gagal dan kemudian dicoba lagi, properti tersebut akan menggunakan kembali nilai waktu yang sama seperti pada percobaan asli, bukan pembaruan pada saat percobaan ulang. Jika transaksi gagal secara permanen, nilai properti akan masih ditetapkan dalam salinan entity dalam memori.

Properti Terstruktur

Anda dapat membuat struktur properti model. Misalnya, Anda dapat menentukan Kontak class model yang berisi daftar alamat, masing-masing dengan struktur internal. Properti terstruktur (jenis StructuredProperty) memungkinkan Anda melakukannya; misalnya:

class Address(ndb.Model):
    type = ndb.StringProperty()  # E.g., 'home', 'work'
    street = ndb.StringProperty()
    city = ndb.StringProperty()
...
class Contact(ndb.Model):
    name = ndb.StringProperty()
    addresses = ndb.StructuredProperty(Address, repeated=True)
...
guido = Contact(
    name='Guido',
    addresses=[
        Address(
            type='home',
            city='Amsterdam'),
        Address(
            type='work',
            street='Spear St',
            city='SF')])

guido.put()

Tindakan ini akan membuat satu entity Datastore dengan properti berikut:

assert guido.name == 'Guido'
addresses = guido.addresses
assert addresses[0].type == 'home'
assert addresses[1].type == 'work'
assert addresses[0].street is None
assert addresses[1].street == 'Spear St'
assert addresses[0].city == 'Amsterdam'
assert addresses[1].city == 'SF'

Dengan membaca kembali, entity tersebut akan merekonstruksi entity Contact asli dengan tepat. Meskipun instance Address ditentukan menggunakan sintaksis yang sama seperti untuk class model, instance tersebut bukan entity yang lengkap. Instance tersebut tidak memiliki kuncinya sendiri di Datastore. ID tersebut tidak dapat diambil secara terpisah dari entity Contact asalnya. Namun, aplikasi dapat membuat kueri untuk nilai masing-masing kolomnya; lihat Pemfilteran untuk Nilai Properti Terstruktur. Perhatikan bahwaaddress.type danaddress.street , danaddress.city dipandang sebagai array paralel dari sudut pandang Datastore, tetapi library NDB menyembunyikan aspek ini dan membuat daftar terkaitAddress instance.

Anda dapat menentukan opsi properti biasa untuk properti terstruktur (kecuali indexed). Nama Datastore adalah argumen posisi kedua dalam kasus ini (yang pertama adalah class model yang digunakan untuk menentukan substruktur).

Jika tidak perlu membuat kueri untuk properti internal substruktur, Anda dapat menggunakan properti terstruktur lokal (LocalStructuredProperty). Jika Anda mengganti StructuredProperty dengan LocalStructuredProperty pada contoh di atas, perilaku kode Python akan sama, tetapi Datastore hanya akan melihat blob buram untuk setiap alamat. Entity guido yang dibuat dalam contoh akan disimpan sebagai berikut: name = 'Guido' address = <opaque blob for {'type': 'home', 'city': 'Amsterdam'}> address = <opaque blob for {'type': 'work', 'city': 'SF', 'street': 'Spear St'}>

Entity akan dibaca kembali dengan benar. Karena properti jenis ini selalu tidak terindeks, Anda tidak dapat membuat kueri nilai alamat.

Catatan: StructuredProperty dengan properti bertingkat (baik terstruktur maupun tidak) hanya mendukung satu lapisan properti berulang. StructuredProperty dapat diulang, atau properti bertingkat dapat diulang, tetapi tidak keduanya. Solusinya adalah menggunakan LocalStructuredProperty, yang tidak memiliki batasan ini (tetapi tidak memungkinkan kueri pada nilai propertinya).

Properti yang Dikomputasi

Properti yang dikomputasi (ComputedProperty) adalah properti hanya baca yang nilainya dihitung dari nilai properti lain oleh fungsi yang disediakan aplikasi. Harap diingat bahwa properti yang dikomputasi hanya mendukung jenis yang didukung oleh properti generik! Nilai yang dihitung ditulis ke Datastore sehingga dapat dikueri dan ditampilkan dalam penampil Datastore, tetapi nilai yang disimpan diabaikan saat entity dibaca kembali dari Datastore; nilai justru akan dihitung ulang dengan memanggil fungsi setiap kali nilai diminta. Contoh:

class SomeEntity(ndb.Model):
    name = ndb.StringProperty()
    name_lower = ndb.ComputedProperty(lambda self: self.name.lower())
...
entity = SomeEntity(name='Nick')
entity.put()

Tindakan ini menyimpan entity dengan nilai properti berikut:

assert entity.name == 'Nick'
assert entity.name_lower == 'nick'

Jika kita mengubah nama menjadi 'Nickie' dan meminta nilai name_lower, metode ini akan menampilkan 'nickie':

entity.name = 'Nick'
assert entity.name_lower == 'nick'
entity.name = 'Nickie'
assert entity.name_lower == 'nickie'

Catatan: Gunakan ComputedProperty jika aplikasi membuat kueri untuk nilai yang dihitung. Jika Anda hanya ingin menggunakan versi turunan dalam kode Python, tentukan metode reguler atau gunakan @property bawaan Python.

Catatan: Jika Anda membuat model tanpa kunci yang ditentukan secara manual, dan mengandalkan Datastore untuk menghasilkan ID entity secara otomatis, maka pada put() pertama Anda ComputedProperty tidak akan dapat membaca kolom ID karena kolom tersebut dihitung sebelum ID dibuat. Jika memerlukan ComputedProperty yang menggunakan ID entity, Anda dapat menggunakan metode allocate_ids untuk menghasilkan ID dan kunci yang akan digunakan untuk membuat entity tersebut, agar ComputedProperty Anda akan dapat mereferensikan ID tersebut pada put() pertama entity.

Properti Pesan Google Protocol RPC

Library Google Protocol RPC menggunakan objek Message untuk data terstruktur; keduanya dapat mewakili permintaan, respons RPC, atau hal-hal lainnya. NDB menyediakan API untuk menyimpan objek Message Google Protocol RPC sebagai properti entity. Misalnya Anda menentukan subclass Message:

from protorpc import messages
...
class Note(messages.Message):
    text = messages.StringField(1, required=True)
    when = messages.IntegerField(2)

Anda dapat menyimpan objek Note di Datastore sebagai nilai properti entity dengan menggunakan msgprop API NDB.

from google.appengine.ext import ndb
from google.appengine.ext.ndb import msgprop
...
class NoteStore(ndb.Model):
    note = msgprop.MessageProperty(Note, indexed_fields=['when'])
    name = ndb.StringProperty()
...
my_note = Note(text='Excellent note', when=50)

ns = NoteStore(note=my_note, name='excellent')
key = ns.put()

new_notes = NoteStore.query(NoteStore.note.when >= 10).fetch()

Jika Anda ingin membuat kueri untuk nama kolom, nama tersebut harus diindeks. Anda dapat menentukan daftar nama kolom yang akan diindeks dengan parameter indexed_fields ke MessageProperty.

MessageProperty mendukung banyak, tetapi tidak semua, Opsi properti. API ini mendukung:

  • name
  • repeated
  • required
  • default
  • choices
  • validator
  • verbose_name

Properti pesan tidak mendukung opsi properti indexed; Anda tidak dapat mengindeks nilai Message. (Anda dapat mengindeks kolom pesan seperti yang dijelaskan di atas.)

Pesan bertingkat (menggunakan MessageField) juga berfungsi:

class Notebook(messages.Message):
    notes = messages.MessageField(Note, 1, repeated=True)
...
class SignedStorableNotebook(ndb.Model):
    author = ndb.StringProperty()
    nb = msgprop.MessageProperty(
        Notebook, indexed_fields=['notes.text', 'notes.when'])

MessageProperty memiliki opsi properti khusus, protocol, yang menentukan cara objek pesan diserialisasi ke Datastore. Nilai adalah nama protokol seperti yang digunakan oleh class protorpc.remote.Protocols. Nama protokol yang didukung adalah protobuf dan protojson; default-nya adalah protobuf.

msgprop juga menentukan EnumProperty, jenis properti yang dapat digunakan untuk menyimpan nilai protorpc.messages.Enum dalam entity. Contoh:

class Color(messages.Enum):
    RED = 620
    GREEN = 495
    BLUE = 450
...
class Part(ndb.Model):
    name = ndb.StringProperty()
    color = msgprop.EnumProperty(Color, required=True)
...
p1 = Part(name='foo', color=Color.RED)
print p1.color  # prints "RED"

EnumProperty menyimpan nilai sebagai bilangan bulat; sebenarnya, EnumProperty adalah subclass dari IntegerProperty. Ini menyiratkan bahwa Anda dapat mengganti nama nilai enum tanpa harus mengubah entity yang sudah disimpan, tetapi Anda tidak dapat mengganti nomornya.

EnumProperty mendukung opsi properti berikut:

  • name
  • indexed
  • repeated
  • required
  • default
  • choices
  • validator
  • verbose_name

Tentang model entity NDB

Model entity NDB dapat menentukan properti. Properti entity sedikit mirip dengan anggota data class Python, yaitu cara terstruktur untuk menyimpan data; properti entity juga mirip dengan kolom dalam skema database.

Aplikasi standar menentukan model data dengan menentukan class yang diwarisi dari Model dengan beberapa atribut class properti. Misalnya,


from google.appengine.ext import ndb
...
class Account(ndb.Model):
    username = ndb.StringProperty()
    userid = ndb.IntegerProperty()
    email = ndb.StringProperty()

Di sini, username, userid, dan email adalah properti dari Account.

Ada beberapa jenis properti lainnya. Beberapa properti berguna untuk menampilkan tanggal dan waktu serta memiliki fitur update otomatis yang mudah.

Aplikasi dapat menyesuaikan perilaku properti dengan menentukan opsi pada properti tersebut; parameter ini dapat memudahkan validasi, menetapkan setelan default, atau mengubah pengindeksan kueri.

Model dapat memiliki properti yang lebih kompleks. Properti berulang mirip dengan daftar. Properti terstruktur mirip dengan objek. Properti terkomputasi hanya baca ditentukan melalui fungsi; hal ini memudahkan untuk menentukan properti dari satu atau beberapa properti lain. Model Expando dapat menentukan properti secara dinamis.