1

I am running django-haystack v2.0.0 with pyelasticsearch v0.3 in one of my projects. I have a SearchView that renders a listing template and i want to integrate result filtering. The search runs fine, but the filters i am using are not working at all ? I use the following filters __contains, __lte, __gte but none of them seems to make a difference to the result list.

So say, I have 10 results rendered from the SearchView based on a search term. On the same template i have a filter form (that uses the GET method) and calls the same SearchView. Now under the SearchView I have a custom private _filter_results method defined as follows.

    def _filter_results(results, filters):
        """  
        This method would return the filtered search results, based on
        the filters applied by a user.
        """

        for item in filters:
            if item == 'location':
                results = results.filter(locations__contains=filters[item])
                print results
            if item == 'age_min':
                results = results.filter(workex_min__gte=filters[item])
            if item == 'age_max':
                results = results.filter(workex_max__lte=filters[item])
        return results

Now, I pass the results to the template as follows:

context {'results' : _filter_results(self.results, self.result_filters)}

self.result_filters is a dictionary of filters that I set in SearchView's __call__ method and it look something like this.

{
    'location' : request.GET.get('location'),
    'age_min' : request.GET.get('age_min'),
    'age_max' : request.GET.get('age_max'),
}

I do not get any errors, and I have double checked that each filter value is being passed to the _filter_results method. But the results still stay the same.

If on a results list of 10 entries i try to filter with a location where none of them contains the location, I still get a result of the same 10 entries back. What could be the reason ?

Amyth
  • 32,527
  • 26
  • 93
  • 135

1 Answers1

1

I havent used Haystack with ElasticSearch but have used it extensively with Solr, but it should work the same with ElasticSearch as well.

You should be using results.narrow() method instead of filter. Filter method will essentially append the filters with the main initially query term and run a 'OR' query between them as the default operator is set as 'OR' in haystack.

The narrow() method is specifically there for filtering the initial set of results and refine them further, also its beneficial to run filter query using narrow as the query constructed in SearchEngine is different and makes better use of inbuilt caching.

def _filter_results(results, filters):
    """  
    This method would return the filtered search results, based on
    the filters applied by a user.
    """

    for item in filters:
        if item == 'location':
            results = results.narrow('locations:%s' % filters[item])
            print results
        if item == 'age_min':
            results = results.narrow('workex_min:[%s TO *]' % filters[item])
        if item == 'age_max':
            results = results.narrow('workex_max:[* TO %s]' % filters[item])
    return results

Again this is how it works with Solr but haystack method concepts are same across and the only difference lies in the backends file for each SearchEngine. You should look at haystack/backends/elasticsearch_backend.py for better understanding.

Also have a look at FacetedSearchView and FacetedSearchForm

Rohan
  • 1,031
  • 7
  • 10