Yep. That's usually the technique I use if I don't embed child objects.

--
Ikai Lan
Developer Programs Engineer, Google App Engine
plus.ikailan.com | twitter.com/ikai



On Tue, Aug 2, 2011 at 9:48 AM, J.Ganesan <[email protected]>wrote:

> 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.
>
>

-- 
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.

Reply via email to