5

Java で書かれた GAE プロジェクトがあり、HRD と解決方法がわからない問題について考えています。

基本的に、システムにユーザーがいます。ユーザーは、ユーザー ID、ユーザー名、電子メール、およびパスワードで構成されます。新しいユーザーを作成するたびに、同じユーザー ID (決して起こらないはずです)、ユーザー名、または電子メールを持つユーザーがまだ存在しないことを確認したいと考えています。

userid がキーなので、これで get を行うと一貫性が保たれると思います。ただし、同じユーザー名または電子メールを持つ可能性のあるユーザーを検索するためにクエリを実行 (およびフィルターを使用) すると、結果が一貫していると確信できません。そのため、誰かが数秒前に同じユーザー名または電子メールでユーザーを作成した場合、クエリでそれが見つからない可能性があります。この問題を回避するために祖先が使用されていることは理解していますが、クエリに使用する祖先がない場合はどうすればよいでしょうか? ユーザーには親がありません。

これについてのご意見と、このような状況でのベスト プラクティスと考えられるものをお聞かせいただければ幸いです。それが何かを変えるなら、GAEにObjectifyを使用しています。

4

4 に答える 4

7

ユーザーエンティティに電子メールやその他の自然キーを使用することはお勧めしません。ユーザーは自分の電子メールアドレスを変更します。誰かが自分の電子メールを変更するたびに、データベース内のすべての外部キー参照を書き換えてしまうことは望ましくありません。

これが私がこの問題をどのように解決するかについての短い宣伝文です:

https://groups.google.com/d/msg/google-appengine/NdUAY0crVjg/3fJX3Gn3cOYJ

@Idが電子メールアドレスの正規化された形式である別のEmailLookupエンティティを作成します(私はすべてを小文字にします-技術的には正しくありませんが、ユーザーが誤ってJoe@example.comを大文字にした場合の多くの苦痛を節約します)。私のEmailLookupは次のようになります。

@Entity(name="Email")
public class EmailLookup {
    /** Use this method to normalize email addresses for lookup */
    public static String normalize(String email) {
        return email.toLowerCase();
    }

    @Id String email;
    @Index long personId;

    public EmailLookup(String email, long personId) {
        this.email = normalize(email);
        this.personId = personId;
    }
}

ユーザーエンティティには(正規化されていない)電子メールフィールドもあります。これは、送信電子メールを送信するときに使用します(誰かにとって重要な場合に備えて大文字と小文字を区別してください)。誰かが特定の電子メールでアカウントを作成するとき、私はXGトランザクションのキーでEmailLookupとUserエンティティをロード/作成します。これにより、個々の電子メールアドレスが一意になることが保証されます。

同じ戦略が他の種類の固有の値にも当てはまります。Facebook ID、ユーザー名など。

于 2012-04-05T16:37:44.837 に答える
3

HRDの結果整合性getを回避する方法は、の代わりにを使用することですquery。これを実行できるようにするには、自然なIDを生成する必要があります。たとえば、リクエストで受信したデータ(電子メールとユーザー名)で構成されるIDを生成します。

HRDは一貫性が高いためget、ユーザーがすでに存在するかどうかを確実に確認できます。

たとえば、読み取り可能な自然IDは次のようになります。

String naturalUserId = userEmail + "-" + userName;

注:実際には、メールは一意です。したがって、これはそれ自体で優れた自然IDです。作り上げたユーザー名を追加する必要はありません。

于 2012-04-05T14:12:21.143 に答える
-1

グループ間トランザクションを有効にして ( https://developers.google.com/appengine/docs/java/datastore/overview#Cross_Group_Transactionsを参照)、1 つのトランザクションでユーザーを探して新しいユーザーを作成することもできます。 .

于 2012-04-05T14:58:13.497 に答える
-1

他に用途がない限り、インデックス付きフィールドとクエリを避けることをお勧めします。これは、key_nameを使用して以前に(Pythonで)行ったことです(エンティティIDはintである必要があるため)。ユーザーにリンクする必要がある他のエンティティの key_name または id を簡単に使用できます。

username = self.request.get('username')
usernameLower = username.lower()
rec = user.get_by_key_name(usernameLower)
if rec is None:
    U = user(
        key_name = usernameLower,
        username = username,
        etc...)
    U.put()
else:
    self.response.out.write(yourMessageHere)
于 2012-04-05T18:02:04.297 に答える