Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Filter Django Haystack results like QuerySet?

Is it possible to combine a Django Haystack search with "built-in" QuerySet filter operations, specifically filtering with Q() instances and lookup types not supported by SearchQuerySet? In either order:

haystack-searched -> queryset-filtered

or

queryset-filtered -> haystack-searched

Browsing the Django Haystack documentation didn't give any directions how to do this.

like image 563
nikola Avatar asked Jan 29 '10 02:01

nikola


People also ask

Can I filter a QuerySet Django?

Working with Filter Easily the most important method when working with Django models and the underlying QuerySets is the filter() method, which allows you to generate a QuerySet of objects that match a particular set of filtered parameters.

Is Django filter lazy?

Django querysets are lazy The above code doesn't run any database queries. You can can take the person_set and apply additional filters, or pass it to a function, and nothing will be sent to the database. This is good, because querying the database is one of the things that significantly slows down web applications.

What is get and filter in Django?

filter(**kwargs) Returns a new QuerySet containing objects that match the given lookup parameters. Basically use get() when you want to get a single unique object, and filter() when you want to get all objects that match your lookup parameters. Follow this answer to receive notifications.

What is Haystack in Django?

Haystack provides modular search for Django. It features a unified, familiar API that allows you to plug in different search backends (such as Solr, Elasticsearch, Whoosh, Xapian, etc.) without having to modify your code.


2 Answers

You could filter your queryset based on the results of a Haystack search, using the objects' PKs:

def view(request):
  if request.GET.get('q'):
    from haystack import ModelSearchForm
    form = ModelSearchForm(request.GET, searchqueryset=None, load_all=True)
    searchqueryset = form.search()
    results = [ r.pk for r in searchqueryset ]

    docs = Document.objects.filter(pk__in=results)
    # do something with your plain old regular queryset

    return render_to_response('results.html', {'documents': docs});

Not sure how this scales, but for small resultsets (a few hundred, in my case), this works fine.

like image 145
ar0n Avatar answered Sep 21 '22 06:09

ar0n


From the docs:

SearchQuerySet.load_all(self)

Efficiently populates the objects in the search results. Without using this method, DB lookups are done on a per-object basis, resulting in many individual trips to the database. If load_all is used, the SearchQuerySet will group similar objects into a single query, resulting in only as many queries as there are different object types returned.

http://django-haystack.readthedocs.org/en/latest/searchqueryset_api.html#load-all

Therefore, after you have a filtered SQS, you can do a load_all() on it and just access the database objects via SearchResult.object. E.g.

sqs = SearchQuerySet()
# filter as needed, then load_all
sqs = sqs.load_all()

for result in sqs:
    my_obj = result.object
    # my_obj is a your model object
like image 38
mynameistechno Avatar answered Sep 20 '22 06:09

mynameistechno