[appengine-java] Re: Model to Optimize Queries

2009-09-22 Thread Sam Walker
Thanks Jason, I realize that I wont be able to do transactions per say
across the entity groups, and that the tasks can be run multiple times. With
those two constraints in mind, I designed both of the tasks described above
(running any of the two multiple times wont have any affect due to the stage
variable/pendingSet, and they rely on transactions within the same entity
group). Can you please take a deeper look on what the tasks actually do and
will they achieve what I am trying to do here. Just want to make sure I am
not missing anything basic with this.

Thanks for bringing out Option 3 as the easy winner with 30s rule I wasn't
considering. Thanks for all your help in general as well!

On Tue, Sep 22, 2009 at 10:39 AM, Jason (Google) apija...@google.comwrote:

 Hi Sam. Based on your design above, I believe you're modeling an unowned
 relationship between articles and reviewers, which makes sense.
 Unfortunately, this means that you cannot use transactions, so you'll have
 to work around this. Also keep in mind that tasks may be executed multiple
 times so you will need to include logic to ensure that, should a task be
 executed a second time, it won't throw off your application's state.
 Regarding the task queue scenarios you laid out, I prefer the third option,
 although the first and second should work. With the first and second
 options, you need to be aware of how many articles and reviewers you're
 processing since tasks are subject to the same 30-second request limits that
 normal requests are. Option 3 neatly avoids this problem, which is one
 reason why I consider it preferable.

 - Jason


 On Sun, Sep 20, 2009 at 8:46 PM, Sam Walker am.sam.wal...@gmail.comwrote:

 Yea, I dont need to query on it, that's why I thought maybe storing in a
 HashMap would save me an extra query. Lets not go that way for now and
 assume I make a new relationship:

 I have another question, I was wondering if I can use TaskQueue to achieve
 some sort of transactions across entities and give my reviewers points (to
 rank them later on) based on their reviews.

 So, once an Article is finalized, I want to give each reviewer some points
 (based on some logic like first reviewer who approved gets the maximum
 points and so on and so forth), I am thinking of having another persistent
 variable in Article named stage, initialized to 0 and a pendingSet in
 Reviewer

 Once everyone approves, I can set stage to 1.

 Task 1:
 For all articles in stage 1:
   For all reviewers in this article
 in a transaction add the given article to pendingSet of the reviewer
 Set article stage to 2

 Task 2:
 For all articles in stage 2:
   For all reviewers in this article:
  in a transaction, remove the article from the pendingSet and add
 points to the reviewer
 Set article stage to 3

 First and foremost, you think this will work, right?

 Secondly, which approach is the best:
 1. Make one  big task which executes both task1 followed by task 2, and
 run it every five minutes or so.
 2. Run both task 1 and task 2 every 5 minutes
 3. Change the tasks so that they take the key of the article as input, and
 kick off Task 1 with key = articleKey after setting the stage to 1, and Task
 1 kicks off Task2 with key = articleKey after setting the stage to 2.

 Please feel free to add more and advise which should be used when.

 Thanks a bunch!


 On Tue, Sep 8, 2009 at 12:03 PM, Jason (Google) apija...@google.comwrote:

 How do you plan to use the HashMap? You won't be able to query on it, so
 if that's a requirement, you'll want to look into adding another
 relationship.

 - Jason

 On Fri, Sep 4, 2009 at 7:14 PM, Sam Walker am.sam.wal...@gmail.comwrote:

 Thanks!

 I am thinking of doing something like this:

 class Article {
   HashSetKey reviewers;
   HashSetString tags;
   int status; // pending, approved, declined - derived from reviewers'
 statuses

   HashMapKey, Review mapping; // Reviewer key to Review mapping to
 prevent storing making another 1:n relationship

   class Review {
 int status; // pending, approved, declined
 String notes;
 ... // anything else
   }
 }

 Do you think this will work? It doesn't get me all the things I want,
 but is still good enough I think (its kind of sad that we can't model this
 common scenario effectively/efficiently).

 Do you recommend doing this HashMap kind of a hacky thing or just make a
 new Entity and a new relationship? Is it worth the saving?


 On Sat, Aug 29, 2009 at 12:28 AM, leszek leszek.ptokar...@gmail.comwrote:


 Let consider a different approach. Take into account that Article and
 Reviewer are rather immutable data (you need adding new article but
 not to change existing), why break this nice feature.
 Consider several classes:
 Article { Key , {tags}  next attribuites }
 Reviewer { Key, mail, ... next attributes }
 ArticleNotReviewedYet { Key articleKey }
 ArticleUnderReview { Key articleKey, Key reviewerKey, int
 reviewResult }
 ArticleReviewed {Key

[appengine-java] Re: Model to Optimize Queries

2009-09-20 Thread Sam Walker
Yea, I dont need to query on it, that's why I thought maybe storing in a
HashMap would save me an extra query. Lets not go that way for now and
assume I make a new relationship:

I have another question, I was wondering if I can use TaskQueue to achieve
some sort of transactions across entities and give my reviewers points (to
rank them later on) based on their reviews.

So, once an Article is finalized, I want to give each reviewer some points
(based on some logic like first reviewer who approved gets the maximum
points and so on and so forth), I am thinking of having another persistent
variable in Article named stage, initialized to 0 and a pendingSet in
Reviewer

Once everyone approves, I can set stage to 1.

Task 1:
For all articles in stage 1:
  For all reviewers in this article
in a transaction add the given article to pendingSet of the reviewer
Set article stage to 2

Task 2:
For all articles in stage 2:
  For all reviewers in this article:
 in a transaction, remove the article from the pendingSet and add points
to the reviewer
Set article stage to 3

First and foremost, you think this will work, right?

Secondly, which approach is the best:
1. Make one  big task which executes both task1 followed by task 2, and run
it every five minutes or so.
2. Run both task 1 and task 2 every 5 minutes
3. Change the tasks so that they take the key of the article as input, and
kick off Task 1 with key = articleKey after setting the stage to 1, and Task
1 kicks off Task2 with key = articleKey after setting the stage to 2.

Please feel free to add more and advise which should be used when.

Thanks a bunch!

On Tue, Sep 8, 2009 at 12:03 PM, Jason (Google) apija...@google.com wrote:

 How do you plan to use the HashMap? You won't be able to query on it, so if
 that's a requirement, you'll want to look into adding another relationship.

 - Jason

 On Fri, Sep 4, 2009 at 7:14 PM, Sam Walker am.sam.wal...@gmail.comwrote:

 Thanks!

 I am thinking of doing something like this:

 class Article {
   HashSetKey reviewers;
   HashSetString tags;
   int status; // pending, approved, declined - derived from reviewers'
 statuses

   HashMapKey, Review mapping; // Reviewer key to Review mapping to
 prevent storing making another 1:n relationship

   class Review {
 int status; // pending, approved, declined
 String notes;
 ... // anything else
   }
 }

 Do you think this will work? It doesn't get me all the things I want, but
 is still good enough I think (its kind of sad that we can't model this
 common scenario effectively/efficiently).

 Do you recommend doing this HashMap kind of a hacky thing or just make a
 new Entity and a new relationship? Is it worth the saving?


 On Sat, Aug 29, 2009 at 12:28 AM, leszek leszek.ptokar...@gmail.comwrote:


 Let consider a different approach. Take into account that Article and
 Reviewer are rather immutable data (you need adding new article but
 not to change existing), why break this nice feature.
 Consider several classes:
 Article { Key , {tags}  next attribuites }
 Reviewer { Key, mail, ... next attributes }
 ArticleNotReviewedYet { Key articleKey }
 ArticleUnderReview { Key articleKey, Key reviewerKey, int
 reviewResult }
 ArticleReviewed {Key articleKey, int totalReviewResult }

 This way if you want:
 - to know the status of the article : find article in the first table
 and find (by looking up the articleKey only) in what table
 (ArticleNotReviewed, ArticleUnderReview, ArticleReviewed) contains the
 articleKey
 - to add new article: add article to Article and entry to
 ArticleNotReviewed
 - to start review: remove article from ArticleNotReviewed and add an
 entry in ArticleUnderReview
 - to add next review result: add next entry to ArticleUnderReview
 - to end up review: remove all articleKey entries in
 ArticleUnderReview and create entry in ArticleReviewed


 Of course, it needs much more elaboration, but may be it is worth
 considering.







 


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



[appengine-java] Re: To specify Key or use auto generation

2009-09-07 Thread Sam Walker
In 1, another problem is that I may not know the Keys of A and B at the
point of creation. For example, lets say I am doing something like this:

class Person {
}

class Group {
  @Persistent(mappedBy = group)
  ArrayListMembership memberships;
}

class Membership {
  Key person;
  Group group;
}


Now I would do:
Group g = new Group();
while(...) {
  Membership m = new Membership();
  g.memberships.add(m);
}
pm.makePersistent(g);

Now, when I create membership, I dont have the Group key (I do have the
person key), I can't really use it to create a new derived key for
membership. Or am I missing something?

On Sun, Sep 6, 2009 at 11:04 PM, Sam Walker am.sam.wal...@gmail.com wrote:

 Lets say there is a relationship between Entities A and B, and I want to
 model it with Entity C.

 Two ways:
 1. Use concatenated Key of A and B for Key of C. Data model will ensure
 there are no duplicates.
 2. Use autogenerated Key and make sure you do not duplicate A B
 relationship in code.

 Which one would you choose? In 1, is a simple concatenation the best way to
 go about it?


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



[appengine-java] Re: Model to Optimize Queries

2009-09-04 Thread Sam Walker
Thanks!

I am thinking of doing something like this:

class Article {
  HashSetKey reviewers;
  HashSetString tags;
  int status; // pending, approved, declined - derived from reviewers'
statuses

  HashMapKey, Review mapping; // Reviewer key to Review mapping to prevent
storing making another 1:n relationship

  class Review {
int status; // pending, approved, declined
String notes;
... // anything else
  }
}

Do you think this will work? It doesn't get me all the things I want, but is
still good enough I think (its kind of sad that we can't model this common
scenario effectively/efficiently).

Do you recommend doing this HashMap kind of a hacky thing or just make a new
Entity and a new relationship? Is it worth the saving?

On Sat, Aug 29, 2009 at 12:28 AM, leszek leszek.ptokar...@gmail.com wrote:


 Let consider a different approach. Take into account that Article and
 Reviewer are rather immutable data (you need adding new article but
 not to change existing), why break this nice feature.
 Consider several classes:
 Article { Key , {tags}  next attribuites }
 Reviewer { Key, mail, ... next attributes }
 ArticleNotReviewedYet { Key articleKey }
 ArticleUnderReview { Key articleKey, Key reviewerKey, int
 reviewResult }
 ArticleReviewed {Key articleKey, int totalReviewResult }

 This way if you want:
 - to know the status of the article : find article in the first table
 and find (by looking up the articleKey only) in what table
 (ArticleNotReviewed, ArticleUnderReview, ArticleReviewed) contains the
 articleKey
 - to add new article: add article to Article and entry to
 ArticleNotReviewed
 - to start review: remove article from ArticleNotReviewed and add an
 entry in ArticleUnderReview
 - to add next review result: add next entry to ArticleUnderReview
 - to end up review: remove all articleKey entries in
 ArticleUnderReview and create entry in ArticleReviewed


 Of course, it needs much more elaboration, but may be it is worth
 considering.

 


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



[appengine-java] Re: Model to Optimize Queries

2009-08-27 Thread Sam Walker
Yes, it is a key. I just wanted to make it obvious which Keys are involved.
I read the Embedded class as well, its not what I want here I think.

How would you model this scenario then? Both models I discussed in my
original post have issues.

On Thu, Aug 27, 2009 at 11:22 AM, Jason (Google) apija...@google.comwrote:

 JDO supports syntax like article.status but App Engine's datastore doesn't
 support joins so you'll have to make article an embedded object in order to
 use the query as you have it below:

 http://code.google.com/appengine/docs/java/datastore/dataclasses.html#Embedded_Classes

 Also, how have you defined reviewerParam? Is it a Key object or are you
 actually passing in the Reviewer object? The latter won't work, but I'll
 follow up about the former (querying on a Key).

 - Jason


 On Sun, Aug 23, 2009 at 11:18 PM, Sam Walker am.sam.wal...@gmail.comwrote:

 Also, I get this error: *Can only filter by properties of a sub-object if
 the sub-object is embedded.* when I tried to access article while setting
 a fitler: query.setFilter(reviewer == reviewerParam   article.status =
 articleStatusParam);

 What am I missing?


 On Sat, Aug 22, 2009 at 6:02 PM, Sam Walker am.sam.wal...@gmail.comwrote:

 In the second model, how will I find all Articles being reviewed by A and
 B?

 The only way I can think of is adding another derived field in Article:

 Article {
   HashSetReview reviews;
   HashSetReviewer reviewers; // keys of Reviewers to help the query
 find all articles reviewed by A and B
   HashSetString tags;
   int status; // derived from all Reviews' statuses.
 }

 Review {
   Article article;
   Reviewer reviewer;
   int status;
 }

 Now I should be able to do reviewers.contains(A.key) and
 reviewers.contains(B.key). Is that the best way?


 On Sat, Aug 22, 2009 at 2:02 PM, Sam Walker am.sam.wal...@gmail.comwrote:

 Oh sweet, I didn't know that.

 That's awesome! Thanks for the quick reply.


 On Sat, Aug 22, 2009 at 1:51 PM, datanucleus 
 andy_jeffer...@yahoo.comwrote:


  I dont think I can do sth like (I can't access article.tags,
 article.status
  as far as I know, correct?):

 Of course you can. JDO spec defines JDOQL, using Java syntax.

  query.setFilter(reviewer == reviewerParam  status == statusParam
 
  article.tags == tagParam  article.status = articleStatusParam);

 What is tagParam ? an element of the hashSet?
 You can't do Collection == element in Java so you can't in JDOQL.
 You could do article.tags.contains(tagParam)








 


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



[appengine-java] Re: Model to Optimize Queries

2009-08-25 Thread Sam Walker
Any ideas, anyone?

On Sun, Aug 23, 2009 at 11:18 PM, Sam Walker am.sam.wal...@gmail.comwrote:

 Also, I get this error: *Can only filter by properties of a sub-object if
 the sub-object is embedded.* when I tried to access article while setting
 a fitler: query.setFilter(reviewer == reviewerParam   article.status =
 articleStatusParam);

 What am I missing?


 On Sat, Aug 22, 2009 at 6:02 PM, Sam Walker am.sam.wal...@gmail.comwrote:

 In the second model, how will I find all Articles being reviewed by A and
 B?

 The only way I can think of is adding another derived field in Article:

 Article {
   HashSetReview reviews;
   HashSetReviewer reviewers; // keys of Reviewers to help the query
 find all articles reviewed by A and B
   HashSetString tags;
   int status; // derived from all Reviews' statuses.
 }

 Review {
   Article article;
   Reviewer reviewer;
   int status;
 }

 Now I should be able to do reviewers.contains(A.key) and
 reviewers.contains(B.key). Is that the best way?


 On Sat, Aug 22, 2009 at 2:02 PM, Sam Walker am.sam.wal...@gmail.comwrote:

 Oh sweet, I didn't know that.

 That's awesome! Thanks for the quick reply.


 On Sat, Aug 22, 2009 at 1:51 PM, datanucleus 
 andy_jeffer...@yahoo.comwrote:


  I dont think I can do sth like (I can't access article.tags,
 article.status
  as far as I know, correct?):

 Of course you can. JDO spec defines JDOQL, using Java syntax.

  query.setFilter(reviewer == reviewerParam  status == statusParam 
  article.tags == tagParam  article.status = articleStatusParam);

 What is tagParam ? an element of the hashSet?
 You can't do Collection == element in Java so you can't in JDOQL.
 You could do article.tags.contains(tagParam)
 





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



[appengine-java] Re: Model to Optimize Queries

2009-08-24 Thread Sam Walker
Also, I get this error: *Can only filter by properties of a sub-object if
the sub-object is embedded.* when I tried to access article while setting a
fitler: query.setFilter(reviewer == reviewerParam   article.status =
articleStatusParam);

What am I missing?

On Sat, Aug 22, 2009 at 6:02 PM, Sam Walker am.sam.wal...@gmail.com wrote:

 In the second model, how will I find all Articles being reviewed by A and
 B?

 The only way I can think of is adding another derived field in Article:

 Article {
   HashSetReview reviews;
   HashSetReviewer reviewers; // keys of Reviewers to help the query find
 all articles reviewed by A and B
   HashSetString tags;
   int status; // derived from all Reviews' statuses.
 }

 Review {
   Article article;
   Reviewer reviewer;
   int status;
 }

 Now I should be able to do reviewers.contains(A.key) and
 reviewers.contains(B.key). Is that the best way?


 On Sat, Aug 22, 2009 at 2:02 PM, Sam Walker am.sam.wal...@gmail.comwrote:

 Oh sweet, I didn't know that.

 That's awesome! Thanks for the quick reply.


 On Sat, Aug 22, 2009 at 1:51 PM, datanucleus andy_jeffer...@yahoo.comwrote:


  I dont think I can do sth like (I can't access article.tags,
 article.status
  as far as I know, correct?):

 Of course you can. JDO spec defines JDOQL, using Java syntax.

  query.setFilter(reviewer == reviewerParam  status == statusParam 
  article.tags == tagParam  article.status = articleStatusParam);

 What is tagParam ? an element of the hashSet?
 You can't do Collection == element in Java so you can't in JDOQL.
 You could do article.tags.contains(tagParam)
 




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



[appengine-java] Model to Optimize Queries

2009-08-22 Thread Sam Walker
Model: Article can have multiple tags and multiple reviewers

Queries I want to do:

1. Find all articles with a particular tag which I have to review
2. Find all articles that are being reviewed by me and someone else

Model I am thinking:

Article {
  HashSetReviewer reviewers;
  HashSetString tags;
}

Now the twist is that reviewers can approve or disapprove the article for
publishing, so I want to show a dashboard where I would do queries like:

1. Articles I still need to review.
2. Articles which you have approved, but haven't been approved by everyone
else (we could be waiting on someone's response or someone could have
declined (you may want to take some action, talk to the other reviewer)).

and I was thinking that there should also be a way to see

3. Articles that I have declined.
4. Articles that have been approved.

I was initially thinking of keeping a HashMapKey, int status; kind of a
thing, but then I would have to go through every Article, that can't be
good. I also thought of doing this:

Article {
  HashSetReview reviews;
  HashSetString tags;
  int status; // derived from all Reviews' statuses.
}

Review {
  Article article;
  Reviewer reviewer;
  int status;
}

I dont think I can do sth like (I can't access article.tags, article.status
as far as I know, correct?):

final Query query = pm.newQuery(Review.class);
query.setFilter(reviewer == reviewerParam  status == statusParam 
article.tags == tagParam  article.status = articleStatusParam);

So, whats the best way to model this scenario, where should I compromise?

Thanks!

P.S. Also wondering how do people search across all these entities so fast?
Whats the catch?

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



[appengine-java] Re: Model to Optimize Queries

2009-08-22 Thread Sam Walker
Oh sweet, I didn't know that.

That's awesome! Thanks for the quick reply.

On Sat, Aug 22, 2009 at 1:51 PM, datanucleus andy_jeffer...@yahoo.comwrote:


  I dont think I can do sth like (I can't access article.tags,
 article.status
  as far as I know, correct?):

 Of course you can. JDO spec defines JDOQL, using Java syntax.

  query.setFilter(reviewer == reviewerParam  status == statusParam 
  article.tags == tagParam  article.status = articleStatusParam);

 What is tagParam ? an element of the hashSet?
 You can't do Collection == element in Java so you can't in JDOQL.
 You could do article.tags.contains(tagParam)
 


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



[appengine-java] Re: Model to Optimize Queries

2009-08-22 Thread Sam Walker
In the second model, how will I find all Articles being reviewed by A and B?

The only way I can think of is adding another derived field in Article:

Article {
  HashSetReview reviews;
  HashSetReviewer reviewers; // keys of Reviewers to help the query find
all articles reviewed by A and B
  HashSetString tags;
  int status; // derived from all Reviews' statuses.
}

Review {
  Article article;
  Reviewer reviewer;
  int status;
}

Now I should be able to do reviewers.contains(A.key) and
reviewers.contains(B.key). Is that the best way?

On Sat, Aug 22, 2009 at 2:02 PM, Sam Walker am.sam.wal...@gmail.com wrote:

 Oh sweet, I didn't know that.

 That's awesome! Thanks for the quick reply.


 On Sat, Aug 22, 2009 at 1:51 PM, datanucleus andy_jeffer...@yahoo.comwrote:


  I dont think I can do sth like (I can't access article.tags,
 article.status
  as far as I know, correct?):

 Of course you can. JDO spec defines JDOQL, using Java syntax.

  query.setFilter(reviewer == reviewerParam  status == statusParam 
  article.tags == tagParam  article.status = articleStatusParam);

 What is tagParam ? an element of the hashSet?
 You can't do Collection == element in Java so you can't in JDOQL.
 You could do article.tags.contains(tagParam)
 



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