【问题标题】:How to implement unique usernames/emails in google firestore如何在 google firestore 中实现唯一的用户名/电子邮件
【发布时间】:2019-12-02 17:11:20
【问题描述】:

我编写了一个连接到 google firestore 作为后端的 rest api。我有一个用户集合,并希望确保每个用户文档都有一个唯一的用户名。我的第一种方法是在数据库中查询具有相同用户名的匹配文档,如果找到,则用户必须选择另一个(在注册时)。

这是我对应的代码(golang)

func (service *Service) CreateUser(ctx context.Context, user domains.User) (domains.User, error) {
    var err error

    err = domains.ValidateNewUser(user)
    if err != nil {
        return user, err
    }

    // Check if email already exists
    unique, err := service.CheckEmailUniqueness(ctx, user.Email)
    if err != nil {
        return user, err
    } else if !unique {
        return user, ErrEmailExists
    }

    // Check if user already exists
    unique, err = service.CheckUsernameUniqueness(ctx, user.Username)
    if err != nil {
        return user, err
    } else if !unique {
        return user, ErrUsernameExists
    }

    docRef, _, err := service.Client.Collection("users").Add(ctx, user)
    if err != nil {
        return user, ErrCreatingUser
    }

    user.UserID = docRef.ID

    return user, nil
}
func (service *Service) CheckUsernameUniqueness(ctx context.Context, username string) (bool, error) {
    iter := service.Client.Collection("users").Where("username", "==", username).Documents(ctx)

    usernameExists := false
    for {
        _, err := iter.Next()
        if err == iterator.Done {
            break
        }
        if err != nil {
            return false, err
        }
        usernameExists = true
        break
    }

    return !usernameExists, nil
}

但是在这种情况下如何防止竞争条件?就像当 2 个不同的用户想要使用相同的用户名并且他们的请求由我的休息服务器的两个不同实例处理时一样。总的来说,我对 firestore 和 NoSQL 非常缺乏经验,所以如果我不明白任何重要的内容,请见谅。

【问题讨论】:

  • 查看 Firestore 中事务的使用,以确保一组操作是原子的。
  • 据我了解,只有在您想防止同时写入同一个文档时,事务才有帮助。但在我的用例中并非如此。我想创建唯一的用户(因此不同的文档具有唯一的用户名)。
  • 事务可用于读写操作。在事务中,您可以读取文档以确保它在创建之前不存在。从这个意义上说,用户可以“保留”他们的用户名,而不必担心另一个用户在事务之外声明它(只要他们都使用事务来保护访问)。
  • 酷!很高兴知道,谢谢

标签: google-app-engine google-cloud-platform google-cloud-firestore


【解决方案1】:

事务就是答案,但您不能在事务内部进行查询,只能通过 ID 获取 https://stackoverflow.com/a/50071736/4458510

一种可能的解决方案是将 ID 设为电子邮件/用户名,但是如果用户想要更改他们的电子邮件,那么 ID 就必须更改,这很糟糕,因为其他东西可能会引用该用户。

一种常见的模式是使用另一个集合来执行唯一性。然后,您将与事务中的“用户”集合和“用户电子邮件”集合进行交互

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-04-15
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 2019-04-26
    • 1970-01-01
    • 2021-03-11
    • 2023-03-10
    相关资源
    最近更新 更多