views:

42

answers:

2

I'm implementing a frontpage with "hot" stories based on a certain ranking algorithm. However, I can't figure out how to pass Appengine's datastore my own sort function (like I can in python with sort(key=ranking_function)). I want something like this:

class Story(db.Model):
    user = db.ReferenceProperty(User)
    text = db.TextProperty()
    def ranking(self):
        # my ranking function, returns an int or something
        return 1
    ranking = property(ranking_function)

So that I can later call:

Story.all().order("ranking").limit(50)

Any idea how to do this using Appengine's datastore models?

+3  A: 

I don't think this is possible with App Engine the way you describe it, but I think it is possible to achieve what you want. You want the datastore to run your ranking function against every element in the datastore, every time you do a query. That is not very scalable, as you could have millions of entities that you want to rank.

Instead, you should just have a integer property called rank, and set it every time you update an entity. Then you can use that property in your order clause.

Peter Recore
Thanks. However, see the accepted answer for a really useful, nifty library!
dave paola
+1  A: 

There's no built in property that handles this, but there's a library, aetycoon, that implements DerivedProperty and other related properties that do what you want. Here's an article on how it works.

Nick Johnson
I did this and it works wonderfully. However, I'm adding alot of properties that seem to throw NotSavedErrors when I try to make a new object with some DerivedProperties. The only solution is to wrap the entire thing in a try-except. It works but it's slightly ugly.Thanks!
dave paola
Can you be more specific? What stacktrace do you get, and under what circumstances?
Nick Johnson