Well, the problem is that the right schema is so heavily dependent on what type of app is being written, and what the data being stored looks like. But here's a quick example:
Some applications need only a short list of values in a single property name. For example, a simple blogging app could use an Entity similar to the below for storing blog posts:
Kind: blogpost
ID: [number allocated by the datastore]
Properties:
blogtitle: "Hi!"
blogtext: "This is my first post on my new blog."
creationdate: 1405643123460 (number of milliseconds since UNIX epoch)
tags: "blog" , "google" , "myfirstpost"
Obviously, the list of tags on a blog post are going to be very short; realistically, you'll never have thousands of tags on a single blog post. So in cases such as this using a list property is fine.
The problem comes when a list could be very, very long. Consider an example app designed to hold a list of the user's favorite bookmarks. A problematic entity could look like this:
Kind: Bookmarks
ID: [number allocated by the datastore]
Properties:
The problem is that some people have a lot of bookmarks, and URLs can get very long. It's very, very easy to have over 1 MB of bookmark links. Instead of that, create an entity per bookmark, then map the bookmark as the child of the user entity. For instance, you could do this:
Kind: UserBookmarks
ID: 1 [number allocated by the datastore]
Properties:
(1 bookmark entity per link, you can set ancestors like this: Entity bookmark = new Entity("Bookmark", id, user_entity.getKey()); )
Kind: Bookmark
Ancestor: User:1 (above entity)
ID: [number allocated by the datastore]
bookmarktitle: " Frozen "
bookmarkdate: 1405643123460
From there, it's easy to query by setting the ancestor (the user
vi...@example.com). This is also a superior arrangement than before since now metadata can be added about the link.
There are other ways to handle this as well. Some developers don't like using ancestor/child relationships; in that case you could skip setting the ancestor on the Bookmark entity, but add a property listing the user the bookmark belongs to:
user: vi...@example.com (or the ID of the user)
. Then query by adding an
AND user=useremail/ID property to the query.
'
Some lists can be dramatically shortened by using IDs instead of exact names. For example, suppose an entity stored a list of books by name. That list of names could be replaced by instead listing the
ISBN number of the books. This makes the list much shorter and simpler to debug.
With that said, a caveat: in cases such as this, it's always important to reevaluate your storage options. Some people try to force their data to fit into the datastore when purchasing a Cloud SQL instance would be better. Always consider your data and the queries you run: some queries and schema will simply be cheaper with Cloud SQL even though the datastore has a free quota. There is nothing wrong with an application using both the datastore and Cloud SQL services: complex applications often do that.
--------------------------------
And finally (whew, this is getting out of hand!) to any college students and fresh graduates reading this: database design and management is a hard, but very fun subject. It's also a well paying job, if that's something that interests you.....