これは、objectify-appengine Google グループでの私の回答からコピーされたものです: https://groups.google.com/forum/?fromgroups#!topic/objectify-appengine/LlOyRJZRbnk
あなたが説明したような「集計データ」を扱うときは、主に3つのオプションがあります。
1) 必要なときに計算する
あなたは、これは高すぎるという結論に達したと思います。
2)バッチ間隔で計算し、この結果を保存します
遅延を伴うため、あまり満足できません。さらに、毎晩データベース全体をくまなく調べる必要はありません。
3) データが変更されたときに集計を更新する
このアプローチでは、データが変更されるたびに多少の作業が必要になりますが、ほぼ間違いなくやりたいことです。
ユーザーごとに何らかの連絡先のコレクションを作成します。メッセージが届いたら、その受信者の送信者の連絡先が存在することを確認してください。受信者が送信者からの最後のメッセージを削除したときに、連絡先も削除したい場合があります。
エンティティ グループのトランザクション レート制限 (1 秒あたり 1 回の書き込み) にぶつからないように注意してください。いくつかのオプションについて説明します。
1)各受信者に連絡先のリストを保存できます:
class Person {
@Id Long id;
Set<Key<Person>> contacts;
}
たとえば、受信者が一度に 20 人の新しい人からメールを受け取った場合、これは明確な問題になります。これはほぼ確実に悪い考えです。一方、連絡先を検索するのは非常に高速で効率的です。マイナーな改善は、これをその人を親とする別のエンティティに移動して、常にそのデータをロードしないようにすることです。
class Contacts {
@Parent Key<Person> owner;
@Id long id = 1; // there's only ever one of these per person, and it should have a predictable key for fetching
Set<Key<Person>> contacts;
}
もちろん、単一エンティティのセットでは、50,000 のエントリ制限が与えられます。最初に 1M のエンティティ サイズ制限に達した場合は、これよりわずかに小さくなる可能性があります。キーが ~20 文字の場合、ほぼ同じになります。これが問題である場合は、複数の Contacts エンティティを許可することができます。その時点で、Brett Slatkin の 2009 年の Google I/O トークの Relation Index Entity パターンのようになります: http://www.youtube.com/watch?v= AgaL6NGpkB8
2)連絡先のリストを別の方向に保存できます
class Person {
@Id Long id;
@Index Set<Key<Peson>> contactOf;
}
これにより、連絡先が誰であるかを見つけるのに少し費用がかかります。単純なキーによる取得ではなく、キーのみのクエリが必要です。しかし、エンティティの書き込み速度によって実際に制限されることはもうありません。人々はおそらく 1 秒間に複数のメッセージを送信することはなく、1000 件のメッセージをまとめて送信する場合は、1 回のトランザクションで contactOf を更新できます。
上記のように、おそらくこのインデックスを別のエンティティに移動する必要があります。
class Contacts {
@Parent Key<Person> person;
@Id long id = 1; // there's only ever one of these per person, and it should have a predictable key for fetching
Set<Key<Person>> of;
}
3)これらの連絡先を完全に別のエンティティに保存することもできます
class Contact {
@Parent Key<Person> person;
@Id Long id;
@Index Key<Person> owner;
}
これは実際には、解決策 2 のスペース効率の悪い方法です。
重要なことは、すべてのメッセージが送受信されるたびにこの構造を更新し続けることです。