Hi John,

Thanks for your reply. I need some time to study and test your codes.

For the last point, Sets.intersection() means we need to load all keys
into memory and perform an in memory Sets.intersection(). Is that
possible to do this by a query directly. In other words, is that
possible to use more than one equality filter on a list property of a
relation entity index for their parents?

Best regards,
Max

On Mar 15, 2:45 pm, John Patterson <jdpatter...@gmail.com> wrote:
> Hi Max,
>
> Regarding your original question, a more efficient solution would be  
> to embed the UesrSkill in the User instance which would allow you to  
> find all results in a single query.  Th problem is that embedded  
> instances can only be queried on a single value.  There would be no  
> way to query skill and ability on the same UserSkill - just "java and c
> ++ with any skill over 3 and any skill over 5"
>
> To solve this you could create a combined property in UserSkill for  
> querying "skillAbility" which would hold values such as "java:5", "c++:
> 4".  This will only work with skill from 0-9 because it depends on  
> lexical ordering (or e.g. 000 - 999)
>
> Both Twig and Objectify but not JDO support embedded collections of  
> instances.
>
> In Twig it would be defined like this
>
> class User
> {
>         @Embed List<UserSkill> skills;
>
> }
>
> class UserSkill
> {
>         String skillAbility;
>         Skill skill;    // direct reference to Skill instance
>         int ability;
>
> }
>
> Disclaimer: I have not tried any of this code - it is just off the top  
> of my head
>
> You would then do a single range query to find "java-5", "java-6,  
> "java-7"...
>
> // find java developers with ability over 5 in a single query
> datastore.find().type(User.class)
>         .addFilter("skillAbility", GREATER_THAN_EQUAL, "java:5")  // range  
> start
>         .addFilter("skillAbility", LESS_THAN, "java-" +  
> Character.MAX_VALUE)  // range end
>         .returnResultsNow();
>
> But that doesn't fully answer your question which includes an AND on  
> multiple property values which is not supported by the datastore.  To  
> do this you will need to perform two queries and merge the results.
>
> Twig has support for merging only OR queries right now so you can do:
>
> // find users with c++ ability > 2 OR java ability > 5
>
> RootFindCommand  or = datastore.find().type(User.class);  // default  
> (only) operator is OR
>
> or.addChildCommand()
>         .addFilter("skillAbility", GREATER_THAN_EQUAL, "java:5")  // range  
> start
>         .addFilter("skillAbility", LESS_THAN, "java-" +  
> Character.MAX_VALUE);  // range end
>
> or.addChildCommand()
>         .addFilter("skillAbility", GREATER_THAN_EQUAL, "java:5")  // range  
> start
>         .addFilter("skillAbility", LESS_THAN, "java-" +  
> Character.MAX_VALUE);  // end
>
> // merges results from both queries into a single iterator
> Iterator<User> results = or.returnResultsNow();
>
> Supporting AND merges is coming!  Add a feature request if you like.  
> But for now you will have to do two separate queries as in the first  
> example and join the results in your own code.  You should make sure  
> both queries are sorted by key then you can "stream" the results  
> without loading them all into memory at once.
>
> // find java developers with ability over 5
> datastore.find().type(User.class)
>         .addSort("skillAbility")      // first sort required to be inequality 
> filter
>         .addSort(Entity.KEY_RESERVED_PROPERTY)  // ensure results in same 
> order
>         .addFilter("skillAbility", GREATER_THAN_EQUAL, "java:5")  // range  
> start
>         .addFilter("skillAbility", LESS_THAN, "java-" +  
> Character.MAX_VALUE)  // range end
>         .returnResultsNow();
>
> // find c++ developers with ability over 2
> datastore.find().type(User.class)
>         .addSort("skillAbility")
>         .addSort(Entity.KEY_RESERVED_PROPERTY)
>         .addFilter("skillAbility", GREATER_THAN_EQUAL, "c++:2")  // range 
> start
>         .addFilter("skillAbility", LESS_THAN, "c++:-" +  
> Character.MAX_VALUE)  // range end
>         .returnResultsNow();
>
> // now iterate through both results and only include those in both  
> iterators
>
> Again, I have not run this code so I might have made a mistake.  Let  
> me know how you get on!  I'll be adding support for these merged AND  
> queries on multiple property values soon - unless someone else wants  
> to contribute it first ;)
>
> To find the similarity between two users is now simple now that they  
> are just a property of the User?  just do a Sets.intersection() of the  
> skills.
>
> John
>
> On 15 Mar 2010, at 12:07, Max wrote:
>
> > Thanks John,
>
> > Bret Slatkins' talk is impressive. Let's say we have m skills with n
> > levels. (i.e., m x n SkillLevel entities). Each SkillLevel entity
> > consists of at least one SkillLevelIndex.
>
> > We define similarity between user A and User B as number of  skills
> > with same level. i.e., number of SkillLevel entities of query:
> > "from SkillLevel where userKeyList contains A and userKeyList contains
> > B"
>
> > It works fine if userKeyList contains all user keys. However, after we
> > applied relation index pattern, we have more than one user keys lists,
> > then how to perform a query to calculate similarity between two users?
>
> > On Mar 10, 12:21 pm, John Patterson <jdpatter...@gmail.com> wrote:
> >> On 10 Mar 2010, at 10:53, Max wrote:
>
> >>> Rusty Wright suggested a list of user keys to be stored in skill
> >>> entity. But that means only 5000 users can have the same skill.
>
> >> If you use the "Relation Index Entity" pattern as described in Bret
> >> Slatkins talk you can store 5000 users per index entity and an
> >> unlimited number of index entities.  This will actually give you much
> >> better query performance too because you will not need to load the
> >> list of 5000 Keys every time you read your main entity.
>
> >> The new release of Twig has direct support for RIE's and can actually
> >> let you query for multiple skills *in parallel* then merge the  
> >> results
> >> and return the parents :
>
> >>http://code.google.com/p/twig-persist/wiki/Using#Relation_Index_Entities
>
> > --
> > 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 
> > athttp://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-j...@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