I've been playing with the "relation index" example from Brett
Slatkin's "Building Scalable Web Applications" talk.

In it, he has something like the following. (These examples are using
Objectify http://code.google.com/p/objectify-appengine/ but it should
be pretty obvious what they are modelling.)

public class Message {
 @Id Long id;
 @Unindexed String body;
}
public class MessageIndex {
 @Id Long id;
 @Parent Key<Message> msg;
 ArrayList<Long> recipients; // user ids
}

That's all hunky dory. Getting all the messages someone has sent you
(all the messages where you are a recipient) proceeds using

a) a key-only query into MessageIndex,
b) a loop to get the parent key of each result,
c) a bulk get() of those parent keys.

I wanted to enhance his example to a bit more of a real twitter-like
use case, and to make sure the messages where you are a recipient are
returned in date-sorted order.

I tried this MessageIndex and composite index:

public class MessageIndex {
 @Id Long id;
 @Parent Key<Message> msg;
 ArrayList<Long> recipients; // user ids
 Date date;
}
   <datastore-index kind="MessageIndex" ancestor="false"
source="auto">
       <property name="recipients" direction="asc"/>
       <property name="date" direction="desc"/>
   </datastore-index>

And this query:
ofy.query(MessageIndex.class).filter("recipients",
user.getId()).order("-date")

The query finds the correct records, but it does not do the sort at
all! This behavior, I think, is hinted at here:
http://code.google.com/appengine/docs/java/datastore/queriesandindexes.html#Restrictions_on_Queries

"One important caveat is queries with both an equality filter and a
sort order on a multi-valued property. In those queries, the sort
order is disregarded."

That seems to be talking about a filter and a sort on the *same*
multi-valued  property, whereas I am sorting on a separate value.


So, if anyone has any hints, my questions are:

1) Am I just doing something wrong, and in fact a
filter-on-list-property plus a sort-on-date-property is possible?

2) Or, is this the expected behaviour.

3) I've got an idea to work around this problem, by appending the
recipients and the dates into the one list property, and using
inequality filters, e.g.

public class MessageIndex {
 @Id Long id;
 @Parent Key<Message> msg;
 ArrayList<String> recipientDates;
}

// create a new MessageIndex
for each recipient:
 long reverseDate = Long.MAX_VALUE - date;
 messageIndex.recipientDates.add(recipient + ":" + reverseDate);

// search for messages to recipient R
ofy.query(MessageIndex.class)
.filter("recipientDates>", recipient + ":")
.filter("recipientDates<", recipient + ":\uFFFd");

I think that would work? But you would end up with a huge number of
unique values in the recipientDates index -- one per recipient per
message. But writes to indexes happen in parallel, so as long as one
is happy paying for the space... shrug.


Thanks in advance for any advice,

=Matt

-- 
You received this message because you are subscribed to the Google Groups 
"Google App Engine" 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?hl=en.

Reply via email to