A few comments:

1. That's more of a 1:1 relationship
2. Try to avoid using the term "child". The reason is that when you start
working with entity groups, you will confuse yourself with terminology. If
you don't understand entity groups yet, take a look at these docs:

http://code.google.com/appengine/docs/python/datastore/entities.html#Entity_Groups_and_Ancestor_Paths

Basically, entity groups represent a hierarchical set of related models. You
should learn about them because they are the unit of atomicity in high
replication datastore (the default).

3. To represent a many-to-many relationship, you would probably want to have
a List property on each entity. A List can contain several keys. The thing
to be aware of here is that for bidirectional many-to-many relationships,
you have to manually make sure the key of the related object is in the
*other* object's list. Example:

Entity ikai = new Entity("User", "ikai");
ikai.setProperty("friends", Arrays.asList(String[] { "proppy", "wesley",
"nick"});

Entity proppy = new Entity("User", "proppy");
proppy.setProperty("friends", Arrays.asList(new String[] { "ikai",
"nick" }));

If proppy (Johan) and I ever have a falling out, you have to remember to
remove "johan" from Ikai's list of friends and vice versa. Normalization
zealots are shaking their heads right now because is possible for many:many
relationships like this to get out of sync.

----
Some insights into working with non-relational persistence:

This isn't the only way to represent child objects. You want to optimize for
reads when possible because *most* applications are read heavy. A rule of
thumb is that the number of reads for a given entity are an order of
magnitude greater than the number of writes. With that in mind, let's talk
about an example of a real world data model I've had to recently write.

My problem: I needed to represent users and teams. A user has a role on a
team. Example:

Ikai - on App Engine team, roles: advocate, support, developer
proppy - on App Engine team, roles: advocate, support, on Apps team roles:
developer, tech writer

In an RDBMS, I'd likely represent this with join tables with an additional
field for the "role". This would likely involve several join tables.

I examined my requirements, and I came to the conclusion that I'd need two
views:

- What roles does a person have? (What teams and roles does Ikai have?)
- Given a team, what other roles do people on that team have? (Give the App
Engine team, what other teams do people on this team have?)

How did I model this?

Two entity kinds: User entity and Team entity.

On the User entity, I stored a JSON serialized property that looks roughly
like this:

{ "teams" : {
   "App Engine" : [ "advocate", "support", "developer" ],
}

When I write a User entity, I also write a Team entity. The Team has a JSON
serialized property that stores all the roles, team members, and a snippet
of information about Team members.

There are tradeoffs in this design, but it suits my purposes:

- It is possible things get out of sync. Since I don't put everything in the
same entity group, I can't do a transaction on a Team and User entity when I
make a change and need to write two entities. I accepted this, but there are
various ways I can mitigate the damage: one way is to use a task queue task
that retries until it executes correctly. Since the action to join or leave
a team can be idempotent, this is something I can run over and over.

- When I read a User entity, I can do this with a single key, so I don't
need to do a query and read related objects. This makes my reads very fast.
The same is true of Team entities. Now, granted, this might be a bit of an
overoptimization, since the number of teams, roles and users might be, worst
case scenario, in the tens of thousands and I can probably just read the
entire datastore and do operations in-memory.

It's possible I'll run into problems later with the way I've designed this,
but rather than try to get everything perfect, I opted with a "good enough"
design without obvious vlaws to get the project off the ground. Technical
debt sucks, but sometimes I see developers too much time overthinking
problems trying to get this perfect. I'm a cynic, but I've accepted that
I'll always look back on software projects and go, "Man, I designed that
poorly" anyway, so I might as well mess them up quickly, have a working
product, figure out where I've messed up, and fix the problems.

Ikai Lan
Developer Programs Engineer, Google App Engine
Blog: http://googleappengine.blogspot.com
Twitter: http://twitter.com/app_engine
Reddit: http://www.reddit.com/r/appengine



On Thu, Jul 21, 2011 at 3:51 PM, Alexander Herrera <
edwinalexande...@gmail.com> wrote:

> Am wondering how in the low level api can i represent a man to many
> relationship , this is a good approximation?
>
>  Entity entityA = new Entity("TypeA");
>     entityA.setProperty("name", "nameUserA");
>
>     Entity entityB = new Entity("TypeA");
>     entityA.setProperty("name", "nameUserB");
>
>     ds.put(entityA);
>     ds.put(entityB);
>
>     Entity entityChild = new Entity("entityChild",entityAKey);
>     entityChild.setProperty("name","child");
>
>      ds.put(entityChild);
>
>     Entity entityChild = new Entity("entityChild",entityBKey);
>     entityChild.setProperty("name","child");
>
>      ds.put(entityChild);
>
> --
> You received this message because you are subscribed to the Google Groups
> "Google App Engine for Java" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/google-appengine-java/-/PWTINDhJTh0J.
> To post to this group, send email to
> google-appengine-java@googlegroups.com.
> To unsubscribe from this group, send email to
> google-appengine-java+unsubscr...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/google-appengine-java?hl=en.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine for Java" group.
To post to this group, send email to google-appengine-java@googlegroups.com.
To unsubscribe from this group, send email to 
google-appengine-java+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-appengine-java?hl=en.

Reply via email to