Filter Django Haystack results like QuerySet?

2019-01-22 22:03发布

问题:

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.

回答1:

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.



回答2:

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


回答3:

If you want to keep up with the pertinence, you have to access the object from the database through "object" :

example in your template:

{% for result in results %}
    {{ result.object.title }}
    {{ result.objects.author }}
{% endfor %}

But this is really bad since haystack will make an extra request like "SELECT * FROM blah WHERE id = 42" on each results.

Seems you're trying to get those object from your database because you didn't put some extra fields in your index ins't it ? If you add the title AND the author in your SearchIndex, then you can just use your results:

{% for result in results %}
    {{ result.title }}
    {{ result.author }}
{% endfor %}

and avoid some extra queries.