1
votes

I have a game where I've (foolishly) made the db key equal to the users login email. I did this several years ago so I've got quite a few users now. Some users have asked to change their email login for my game. Is there a simple way to change the key? As far as I can tell I'd need to make a new entry with the new email and copy all the data across, then delete the old db entry. This is the user model but then I've got other models, like one for each game they are involved in, that store the user key so I'd have to loop though all of them as well and swap out for the new key.

Before I embark on this I wanted to see if anyone else had a better plan. There could be several models storing that old user key so I'm also worried about the process timing out.

It does keep it efficient to pull a db entry as I know the key from their email without doing a search, but it's pretty inflexible in hindsight

2

2 Answers

3
votes

This is actually why you don't use a user's email as their key. Use ndb's default randomly generated key ids.

The efficiency you're referring is not having to query the user's email to retrieve the user id. But that only happens once on user login or from your admin screens when looking at someones account.

You should rip the bandade off now and do a schema-migration away from this model.

  1. Create a new user model (i.e. UsersV2) and clone your existing user model into it to generate new ids.
  2. On all models that reference it add a duplicate field user_v2 = ndb.KeyProperty(UsersV2) and populate it with the new key.
  3. Delete the legacy user model

You should use the taskqueue to do something like this and then you won't have to worry about the process timing out:

https://cloud.google.com/appengine/articles/update_schema

Alternatively, if you are determined to do this cascading update everytime a user changes an email, you could set up a similar update_schema task for just that user.

0
votes

I ended up adding a new property to my user model and running a crawler to copy the string key (the email) to that new property. I changed my code search for that property rather then the key string to get a user item. Most of my users still have keys that equal their email, but I can safely ignore them as if the string is meaningless. I can now change a users email easily without making a new recored and my other models that have pointers to these user keys can remain unchanged.