Well, it sucks but it's true. There's a bunch of noise on the Internet about how to do unique constraints in Google App Engine, but it seems like these are the only two safe ways. The thing to remember is, the only uniqueness that GAE will guarantee is on key names.

Approach #1: Make the unique field be the key name

As long as you promise to yourself that you'll never need to change the value, then you should make the unique field be the "key name" in the table. Then you can call db.Model.get_or_insert(key_name) to either retrieve an existing one or create a new one. Too bad in the real world, it's really hard to find something like this. Email addresses never change? Let me check my hotmail account. Social security numbers never change? Well, unless there was a typo. Every time I think I found a unique field that can never change, I'm proven wrong. So you'll never catch me doing this. But YMMV.

Approach #2: Create a separate table to track all used ids

This is pretty slick -- I found it in this article: Add a Unique Constraint to Google App Engine. The approach is to create a new table called Unique, and make the "key name" of each row in Unique be a combination of the name of the table and the unique field value. The downside is that you have extra storage overhead: a new table with the list of unique fields, plus the default indices that GAE makes for it. This is fairly analogous to declaring a unique index in SQL databases, since a unique SQL index is merely a persisted list of unique fields. There's just less overhead in a SQL database implementation because it's only one list, whereas in GAE this user-generated unique index is really one list (for the table) plus the default indices GAE makes for any entity.

I must say that Google is aware of this issue. It looks like they'd have to make some major architectural changes to implement this. My guess is if they ever fix this, they'll sneak in approach #2, above their BigTable support and below the API that us users use.


comments powered by Disqus