Search code examples
google-app-enginewebapp2app-engine-ndb

Maintain uniqueness of a property in the NDB database


An NDB model contains two properties: email and password. How to avoid adding to the database two records with the same email? NDB doesn't have UNIQUE option for a property, like relational databases do.

Checking that new email is not in the database before adding—won't satisfy me, because two parallel processes can both simultaneously do the checking and each add the same email.

I'm not sure that transactions can help here, I am under this impression after reading some of the manuals. Maybe the synchronous transactions? Does it mean one at a time?


Solution

  • Create the key of the entity by email, then use get_or_insert to check if exists.

    Also read about keys , entities. and models

    #ADD
    key_a = ndb.Key(Person, email);
    person = Person(key=key_a)
    person.put()
    
    #Insert unique    
    a = Person.get_or_insert(email)
    

    or if you want to just check

    #ADD
    key_a = ndb.Key(Person, email);
    person = Person(key=key_a)
    person.put()
    
    #Check if it's added
    new_key_a =ndb.Key(Person, email);
    a = new_key_a.get()
    if a is not None:
        return
    

    Take care. Changing email will be really difficult (need to create new entry and copy all entries to new parent).

    For that thing maybe you need to store the email, in another entity and have the User be the parent of that.

    Another way is to use Transactions and check the email property. Transaction's work in the way: First that commits is the First that wins. A concept which means that if 2 users check for email only the first (lucky) one will succeed, thus your data will be consistent.