Reputation: 375
In my Appengine (using ndb) application I store users and both username and email need to be unique. I also need to be able to update progress (save level if higher than previously stored level), change email and pw and delete account.
I noticed that it is not possible to query without ancestors in a transaction. But creating an ancestor is NOT a solution since that would limit the number of writes to 1 per second which is not OK if the app gets popular. So I need another solution.
Is it possible to use the Key? Yes, but that only makes the username unique, how can I make sure noone is reusing the email for another account?
Upvotes: 2
Views: 82
Reputation: 16563
You should be able to use a cross group transaction for this along with an entity that exists solely for reserving email addresses.
For your User
entity, you could use the username as the key name. When creating a user, you also create an EmailReservation
entity that has the user's email address as a key name.
You then use a cross-group transaction to create a new user:
@ndb.transactional(xg=True)
def create_user(user_name, email):
user = User.get_by_id(user_name)
email_reservation = EmailReservation.get_by_id(email)
if user or email_reservation:
# Either the user_name or email is already in use so stop
return None
# Create the user and reserve the email address so others can't use it
user = User(id=user_name)
email_reservation = EmailReservation(id=email)
ndb.put_multi(user, email_reservation)
return user
Upvotes: 2