views:

377

answers:

2

I use Djapian to search for object by keywords, but I want to be able to filter results. It would be nice to use Django's QuerySet API for this, for example:

if query.strip():
    results = Model.indexer.search(query).prefetch()
else:
    results = Model.objects.all()
results = results.filter(somefield__lt=somevalue)
return results

But Djapian returns a ResultSet of Hit objects, not Model objects. I can of course filter the objects "by hand", in Python, but it's not realistic in case of filtering all objects (when query is empty) - I would have to retrieve the whole table from database.

Am I out of luck with using Djapian for this?

A: 

I dont know Djapian, but i am familiar with xapian. In Xapian you can filter the results with a MatchDecider.

The decision function of the match decider gets called on every document which matches the search criteria so it's not a good idea to do a database query for every document here, but you can of course access the values of the document.

For example at ubuntuusers.de we have a xapian database which contains blog posts, forum posts, planet entries, wiki entries and so on and each document in the xapian database has some additional access information stored as value. After the query, an AuthMatchDecider filters the potential documents and returns the filtered MSet which are then displayed to the user.

If the decision procedure is as simple as somefield < somevalue, you could also simply add the value of somefield to the values of the document (using the sortable_serialize function provided by xapian) and add (using OP_FILTER) an OP_VALUE_RANGE query to the original query.

tux21b
+4  A: 

I went through its source and found that Djapian has a filter method that can be applied to its results. I have just tried the below code and it seems to be working.

My indexer is as follows:

class MarketIndexer( djapian.Indexer ):

    fields = [ 'name', 'description', 'tags_string', 'state']
    tags = [('state', 'state'),]

Here is how I filter results (never mind the first line that does stuff for wildcard usage):

objects = model.indexer.search(q_wc).flags(djapian.resultset.xapian.QueryParser.FLAG_WILDCARD).prefetch()
objects = objects.filter(state=1)

When executed, it now brings Markets that have their state equal to "1".

shanyu