Pertanyaan Bagaimana cara saya mendefinisikan properti unik untuk Model di Google App Engine?


Saya butuh beberapa properti untuk menjadi unik. Bagaimana saya bisa mencapai ini?

Apakah ada sesuatu seperti itu unique=True?

Saya menggunakan Google App Engine untuk Python.


32
2017-07-26 21:41


asal


Jawaban:


Tidak ada kendala bawaan untuk memastikan suatu nilai unik. Namun Anda dapat melakukan ini:

query = MyModel.all(keys_only=True).filter('unique_property', value_to_be_used)
entity = query.get()
if entity:
    raise Exception('unique_property must have a unique value!')

saya menggunakan keys_only=True karena itu akan meningkatkan sedikit kinerja dengan tidak mengambil data untuk entitas.

Metode yang lebih efisien adalah menggunakan model terpisah tanpa bidang yang nama kuncinya terdiri dari nilai nama properti. Maka Anda bisa menggunakan get_by_key_name untuk mengambil satu atau lebih dari nama-nama kunci gabungan ini dan jika Anda mendapatkan satu atau lebih tidak-None nilai, Anda tahu ada nilai duplikat (dan memeriksa nilai mana yang tidak None, Anda akan tahu mana yang tidak unik.)


Sebagai satu per satu disebutkan dalam komentar, pendekatan-pendekatan ini - dengan cara mendapatkan yang pertama, menempatkan sifat selanjutnya - menjalankan masalah konkurensi risiko. Secara teoritis, entitas dapat dibuat hanya setelah memeriksa nilai yang ada, dan kemudian kode setelah cek akan tetap dijalankan, yang mengarah ke nilai duplikat. Untuk mencegah hal ini, Anda harus menggunakan transaksi: Transaksi - Google App Engine


Jika Anda mencari untuk memeriksa keunikan semua entitas dengan transaksi, Anda harus menempatkan semuanya dalam kelompok yang sama menggunakan metode pertama, yang akan sangat tidak efisien. Untuk transaksi, gunakan metode kedua seperti ini:

class UniqueConstraint(db.Model):
    @classmethod
    def check(cls, model, **values):
        # Create a pseudo-key for use as an entity group.
        parent = db.Key.from_path(model.kind(), 'unique-values')

        # Build a list of key names to test.
        key_names = []
        for key in values:
            key_names.append('%s:%s' % (key, values[key]))

        def txn():
            result = cls.get_by_key_name(key_names, parent)
            for test in result:
                if test: return False
            for key_name in key_names:
                uc = cls(key_name=key_name, parent=parent)
                uc.put()
            return True

        return db.run_in_transaction(txn)

UniqueConstraint.check(...) akan berasumsi bahwa setiap pasangan kunci / nilai harus unik untuk mengembalikan kesuksesan. Transaksi ini akan menggunakan satu grup entitas untuk setiap jenis model. Dengan cara ini, transaksi dapat diandalkan untuk beberapa bidang yang berbeda sekaligus (hanya untuk satu bidang, ini akan jauh lebih sederhana.) Juga, bahkan jika Anda memiliki bidang dengan nama yang sama dalam satu atau lebih model, mereka tidak akan bertentangan dengan satu sama lain.


21
2017-07-26 22:13



Google telah menyediakan fungsi untuk melakukan itu:

http://code.google.com/appengine/docs/python/datastore/modelclass.html#Model_get_or_insert

Model.get_or_insert(key_name, **kwds)

Berusaha mendapatkan entitas jenis model dengan nama kunci yang diberikan. Jika ada, get_or_insert () hanya mengembalikannya. Jika tidak ada, entitas baru dengan jenis, nama, dan parameter yang diberikan dalam kwds dibuat, disimpan, dan dikembalikan.

Dapatkan dan berikutnya (mungkin) put dibungkus dalam transaksi untuk memastikan atomicity. Ini berarti bahwa get_or_insert () tidak akan pernah menimpa entitas yang ada, dan akan memasukkan entitas baru jika dan hanya jika tidak ada entitas dengan jenis dan nama yang diberikan.

Dengan kata lain, get_or_insert () setara dengan kode Python ini:

def txn():
  entity = MyModel.get_by_key_name(key_name, parent=kwds.get('parent'))
  if entity is None:
    entity = MyModel(key_name=key_name, **kwds)
    entity.put()
  return entity
return db.run_in_transaction(txn)

Argumen:

key_name   Nama untuk kunci entitas ** kwds   Argumen kata kunci untuk diteruskan ke konstruktor kelas model jika instance dengan nama kunci yang ditentukan tidak ada. Argumen orang tua diperlukan jika entitas yang diinginkan memiliki orang tua.

Catatan: get_or_insert () tidak menerima objek RPC.

Metode mengembalikan instance kelas model yang mewakili entitas yang diminta, apakah itu ada atau dibuat oleh metode. Seperti halnya semua operasi datastore, metode ini dapat meningkatkan TransactionFailedError jika transaksi tidak dapat diselesaikan.


24
2018-04-29 08:44