There's two main things to get used to about the App Engine datastore when compared to 'traditional' relational databases:
- The datastore makes no distinction between inserts and updates. When you call put() on an entity, that entity gets stored to the datastore with its unique key, and anything that has that key gets overwritten. Basically, each entity kind in the datastore acts like an enormous map or sorted list.
- Querying, as you alluded to, is much more limited. No joins, for a start.
The key thing to realise - and the reason behind both these differences - is that Bigtable basically acts like an enormous ordered dictionary. Thus, a put operation just sets the value for a given key - regardless of any previous value for that key, and fetch operations are limited to fetching single keys or contiguous ranges of keys. More sophisticated queries are made possible with indexes, which are basically just tables of their own, allowing you to implement more complex queries as scans on contiguous ranges.
Once you've absorbed that, you have the basic knowledge needed to understand the capabilities and limitations of the datastore. Restrictions that may have seemed arbitrary probably make more sense.
The key thing here is that although these are restrictions over what you can do in a relational database, these same restrictions are what make it practical to scale up to the sort of magnitude that Bigtable is designed to handle. You simply can't execute the sort of query that looks good on paper but is atrociously slow in an SQL database.
In terms of how to change how you represent data, the most important thing is precalculation. Instead of doing joins at query time, precalculate data and store it in the datastore wherever possible. If you want to pick a random record, generate a random number and store it with each record. There's a whole cookbook of this sort of tips and tricks here.
[Update April 2016] This answer is now outdated, custom naked domain mapping is supported, see Lawrence Mok's answer.
I have figured it out!
First off: it is impossible to link something like mydomain.com
with your appspot app. This is considered a naked domain, which is not supported by Google App Engine (anymore). Strictly speaking, the answer to my question has to be "impossible". Read on...
All you can do is add subdomains pointing to your app, e.g myappid.mydomain.com
. The key to get your top level domain linked to your app is to realize that www
is a subdomain like any other!
myappid.mydomain.com
is treated exactly the same as www.mydomain.com
!
Here are the steps:
- Go to appengine.google.com, open your app
- Administration > Versions > Add Domain... (your domain has to be linked to your Google Apps account, follow the steps to do that including the domain verification.)
- Go to www.google.com/a/yourdomain.com
- Dashboard > your app should be listed here. Click on it.
- myappid settings page > Web address > Add new URL
- Simply enter
www
and click Add
- Using your domain hosting provider's web interface, add a CNAME for
www
for your domain and point to ghs.googlehosted.com
Now you have www.mydomain.com
linked to your app.
I wished this would have been more obvious in the documentation...Good luck!
Best Answer
If you're talking about the live datastore, open the dashboard for your app (login on appengine) then datastore --> dataviewer, select all the rows for the table you want to delete and hit the delete button (you'll have to do this for all your tables). You can do the same programmatically through the remote_api (but I never used it).
If you're talking about the development datastore, you'll just have to delete the following file: "./WEB-INF/appengine-generated/local_db.bin". The file will be generated for you again next time you run the development server and you'll have a clear db.
Make sure to clean your project afterwards.
This is one of the little gotchas that come in handy when you start playing with the Google Application Engine. You'll find yourself persisting objects into the datastore then changing the JDO object model for your persistable entities ending up with obsolete data that'll make your app crash all over the place.