2

私は ZODB のインストールを行っており、数百万個のさまざまな種類のオブジェクトを整理する必要があります。Table属性またはこれらの属性の組み合わせによってオブジェクトにインデックスを付ける BTree を含む汎用コンテナー クラスがあります。データの一貫性は非常に重要であるため、インデックス作成の対象となる属性に書き込むと、インデックスが自動的に更新されるようにしたいと考えています。したがって、obj.a = xすべての新しい従属インデックス エントリを計算し、衝突があるかどうかを確認し、最後にインデックスと値を書き込むには、シンプルで十分なはずです。

一般的に、私はそのためにライブラリを喜んで使用するので、repoze.catalogIndexedCatalogを見ていましたが、それにはあまり満足していませんでした。IndexedCatalog はかなり長い間死んでいるように見え、オブジェクトへの変更に対してある種の一貫性を提供していません。repoze.catalog は、より使用され、アクティブになっているようですが、私が理解している限り、この種の一貫性も提供していません。ここで何かを見逃した場合は、それについて聞きたいですし、再発明するよりも再利用することを好みます.

したがって、問題のライブラリを見つけようとする以外に、記述子を使用してデータオブジェクト属性への書き込みアクセスをインターセプトし、Tableクラスにインデックスを変更する魔法を行わせる必要があります。そのために、記述子インスタンスは、どのTableインスタンスと対話する必要があるかを知る必要があります。現在の実装は次のようになります。

class DatabaseElement(Persistent):
    name = Property(constant_parameters)
    ...

class Property(object):
    ...
    def __set__(self, obj, name, val):
        val = self.check_value(val)
        setattr(obj, '_' + name, val)

これらのDatabaseElementクラスが生成されるとき、データベースとその中のオブジェクトはまだ作成されていません。したがって、この素敵な回答で述べたように、オブジェクトをインスタンス化引数としてTable渡すことなく、オブジェクトを見つけるために、おそらくシングルトンルックアップメカニズムを作成する必要があります。Propertyもっとエレガントな方法はありますか?記述子自体を永続化しますか? 提案やベストプラクティスの例を歓迎します!

4

1 に答える 1

0

それで、やっと自分に気がつきました。ソリューションには 3 つの部分があります。醜いシングルトンは必要ありません。Table衝突をチェックするロジックを提供し、醜い回避策なしDatabaseElementで責任を検索する機能を取得し、インデックス付きの値が書き込まれる前にインデックスが更新されるようにします。ここにいくつかのスニペットがあります。主な手がかりは のテーブル ルックアップです。また、それがどこにも文書化されているのを見ませんでした。おまけ: 単一の値への書き込みを検証するだけでなく、複数のインデックス付きの値の変更を一度に確認することもできます。TablePropertyDatabaseElement

class Table(PersistentMapping):
    ....
    def update_indices(self, inst, updated_values_dict):
        changed_indices_keys = self._check_collision(inst, updated_values_dict)
        original_keys = [inst.key(index) for index, tmp_key in changed_indices_keys]
        for (index, tmp_key), key in zip(changed_indices_keys, original_keys):
            self[index][tmp_key] = inst
            try:
                del self[index][key]
            except KeyError:
                pass


class DatabaseElement(Persistent):
    ....
    @property
    def _table(self):
        return self._p_jar and self._p_jar.root()[self.__class__.__name__]

    def _update_indices(self, update_dict, verify=True):
        if verify:
            update_dict = dict((key, getattr(type(self), key).verify(val)) 
                                for key, val in update_dict.items()
                                if key in self._key_properties)
        if not update_dict:
            return
        table = self._table
        table and table.update_indices(self, update_dict)


class Property(object):
    ....
    def __set__(self, obj, val):
        validated_val = self.validator(obj, self.name, val)
        if self.indexed:
            obj._update_indices({self.name: val}, verify=False)
        setattr(obj, self.hidden_name, validated_val)
于 2012-10-01T08:44:37.740 に答える