Pergunta

What's the best practice for filtering based on a foreign key's property in a non-relational database? I understand that the lack of join support makes things more complicated, and so I was wondering how others got around it.

In my case, I have events, which belong to sites, which belong to regions. I want to filter all events in a given region. An Event has a site property that is a foreign key to a Site, which in turn has a region foreign key to a Region:

region = Region.objects.get(id=regionID)
events = Event.objects.filter(site__region=region)

This doesn't work, because site__region requires a join and that's not supported on django-nonrel running on Google App Engine. (I get Caught DatabaseError while rendering: This query is not supported by the database. as an error.) I've thus been iterating through events, adding those that match to a list:

events = list()
region = Region.objects.get(id=regionID)
for event in Event.object.all():
    if event.site.region==region:
        events.append(event)

Is this a good way to be doing things? Is there something silly that I've overlooked? Thanks in advance!

Foi útil?

Solução

That's a very inefficient solution because you dereference site and region, causing lots and lots of queries. This will not scale beyond maybe 100 events in your DB.

The best solution is to denormalize your data by copying e.g. the region's id into Event on save(). Then you can directly do Event.objects.filter(region_id=regionID). The resulting code becomes less clean and maintainable, but that's the way things work on non-relational DBs, today.

All I can say right now is: Wait until the end of January if you can. ;)

Outras dicas

January has gone and dbindexer now supports simple JOINS. You can read about here: http://www.allbuttonspressed.com/blog/django/joins-for-nosql-databases-via-django-dbindexer-first-steps

If you are already using dbindexer you should simply register your index using something like this:

# photo/dbindexes.py:

from models import Event
from dbindexer.lookups import StandardLookup
from dbindexer.api import register_index

register_index(Event, {'site__region': StandardLookup(),})
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top