Is this alternative fine ?
Entity associationEntity = new Entity("Association");
associationEntity.setUnindexedProperty( "key1List" ,
Arrays.asList( Key[] { k1,k1,k2,k3,k3 } ) ) ;
associationEntity.setUnindexedProperty( "key2List" ,
Arrays.asList( Key[] { k8,k6,k4,k1,k7 } ) ) ;
// the developer has to ensure that the cardinality of key1List equals
that of key2List.
I feel this parallels rdbms representation of many-to-many
relationship.
J.Ganesan
www.DataStoreGwt.com
On Jul 22, 8:21 pm, "Ikai Lan (Google)" <[email protected]> wrote:
> 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#...
>
> 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 <
>
>
>
>
>
>
>
> [email protected]> 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
> > [email protected].
> > To unsubscribe from this group, send email to
> > [email protected].
> > 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 [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/google-appengine-java?hl=en.