7

私は Objectify にかなり慣れていないので、何かを行う最善の方法について簡単な質問がありました。

人々がメッセージを送受信できるアプリケーションがあるとしましょう (簡単にするために電子メールを考えてみてください)。アプリが読み込まれるときに、特定のユーザーにメッセージを送信したすべての連絡先からのすべてのメッセージを読み込みたくありません。それはもったいないでしょう。代わりに、アプリで連絡先のリストを表示できるように、ユーザーがメッセージを送信した (既読または未読) すべての連絡先を読み込みたいと考えています。ユーザーが特定の連絡先をクリックすると、すべてを読み込みたいその連絡先からのメッセージをユーザーに表示します。

アカウントのすべてのメッセージを読み込まないと、これを行う良い方法が見つかりません。多対 1 の関係に関する Objectify wiki を読みましたが、これを行うための非常に非効率的でない良い方法をまだ思いつきません。オブジェクト化サイトが推奨する方法では、特定のユーザーのすべてのメッセージを読み込んで、一意の連絡先を解析する必要があるようです。

App Engine の読み取りと書き込みをできるだけ少なくしようとしており、可能な場合は読み取りの代わりにスモールを使用しようとしています (これを作成している間、アプリを実行するための全体的なコストは私の大きな懸念事項です)。 .

Objectify では、これをどのように行うべきですか?

4

1 に答える 1

11

これは、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 のスペース効率の悪い方法です。

重要なことは、すべてのメッセージが送受信されるたびにこの構造を更新し続けることです。

于 2012-02-16T17:20:19.720 に答える