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.
