views:

35

answers:

3

I have model which looks like this:

class Example (db.Model) :
 name = db.StringProperty()
 tags = db.StringListProperty()

I first query for a tag to get the list of entities which have them:

results = Example.all().filter("tags =", tagSearch).fetch(100)

This gives me a list of entities containing the "tagSearch" in their "tags" list.

Here is how a sample of the result entities would look like:

entityA = [tagSearch, m, n, o, ....]

entityB = [a, b, c, tagSearch, ... ]

entityC = [a, tagSearch, a, ,a ,x ....... ....]

I want to sort all the entities in the result set based on the position of the item tagSearch in them, in descending order.

basically - entityA, entityC, entityB 

How do I do this? note I am running this on appengine ...

also assumption given than tagSearch will occur only once in any list.

Any help will be highly appreciated.

+1  A: 

You won't be able to sort these in the query, as far as I know. So the only alternative is to fetch them all and sort them accordingly in your code.

This may not be feasibly performant depending on the number of entities you'd have to return, so you may want to limit the entities in some other way before fetching.

Jason Hall
The issue is I will have to run this algo on all the retrieved entries at the same time to get the right result set. But is this not a really common problem I am citing here? It's a standard sort problem. Would be shocking if app engine fails to deliver on such a common problem.
demos
It doesn't sound like a very common problem to me. How would you do this in SQL -- would you say SQL is failing to deliver by not making this easy?
Jason Hall
+1  A: 

I agree with Jason Hall that given your model it's not going to be doable with a query.

You could try changing your model to something like this:

class Example (db.Model) :
    name = db.StringProperty()

class ExampleTag(db.Model):
    example_id = db.IntegerProperty()
    tag_name = db.StringProperty()
    tag_rank = db.IntegerProperty()

Then you run your query like this:

query = ExampleTag.all()
query.filter('tag_name =', 'tagSearch')
query.order('tag_rank')
tags = query.fetch(100)

examples = Example.get_by_ids([x.example_id for x in tags])
hwiechers
This solution only works if he only ever sorts on a single tag (eg, 'thistag' but never 'thattag')!
Nick Johnson
+2  A: 

The only way I can think of to do this is to modify your tag list to include positions, and use an inequality filter. For example, you could modify the tags to be of the format "tag:ordinal", where ordinal is the position in the list (entityA would thus have ["tagSearch:0", "m:1", "n:2", "o:3"]). Then, instead of doing an equality filter, you perform a query such as this one:

results = Example.all().filter("tags >=", tagSearch + u":").filter("tags <", tagSearch + u":\ufffd").fetch(100)

The result set will thus be ordered by the position the searched-for tag appears in the list. The downside is that you can now only query for a single tag at a time - multiple inequality filters aren't possible in App Engine.

Nick Johnson