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 jenis, lihat properti dan jenis nilai.

Properti dan jenis 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 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, urutannya 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 buram dan tidak diindeks (lihat Properti Terstruktur).
Argumen kata kunci opsional: compressed.
JsonProperty Nilai adalah objek Python (seperti daftar atau 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, 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 dipanggil dengan 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 langsung 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).

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.)

Properti Terstruktur

Anda dapat membuat struktur properti model. Misalnya, Anda dapat menentukan class model Kontak 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 entitas Contact asalnya. Namun, aplikasi dapat membuat kueri untuk nilai setiap kolomnya; lihat Pemfilteran untuk Nilai Properti Terstruktur. Perhatikan bahwa address.type, address.street, dan address.city dipandang sebagai array paralel dari sudut pandang Datastore, tetapi library NDB menyembunyikan aspek ini dan membuat daftar instance Address yang sesuai.

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. Entitas 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.

Properti yang Dikomputasi

Properti yang dikomputasi (ComputedProperty) adalah properti hanya baca yang nilainya dihitung dari nilai properti lain oleh fungsi yang disediakan aplikasi. Perhatikan 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'

Properti Pesan RPC Google Protocol

Library Google Protocol RPC menggunakan objek Message untuk data terstruktur; objek tersebut dapat mewakili permintaan, respons RPC, atau hal lainnya. NDB menyediakan API untuk menyimpan objek Message RPC Google Protocol 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. Nilainya 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 mewarisi dari Model dengan beberapa atribut class properti. Contoh:


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.