toastdriven/django-haystack — Issue #490: SearchQuerySet.exclude together with SearchQuerySet.model and no other filters results in query with no results in SOLR
Author: picturedots
Created: 2012-01-26 19:03:02+00:00
State: open

When using SearchQuerySet().exclude together with SearchQuerySet().model and with no other SearchQuerySet().filter, there are unexpectedly no search results from SOLR. It appears that the "q" argument that is sent to SOLR has an extra parenthesis.

This problem does not occur if there are any filter statements in the SearchQuerySet.

As a workaround, I replaced my SearchQuerySet().models call with an explicit filter to the django_ct field. This seems to work fine:

#OLD
#results = results.models(UserProfile)

#NEW
results = results.filter(django_ct="people.userprofile")

Example of the bug (using a model people.UserProfile with a MultiValue field called personal_tags)

>>> # FIRST CASE:
>>> SearchQuerySet().filter(personal_tags="paris").exclude(personal_tags="london").models(UserProfile)
[<SearchResult: people.userprofile (pk=u'3')>]
>>> # SECOND CASE:
>>> SearchQuerySet().exclude(personal_tags="london").models(UserProfile)
[]
>>> # THIRD CASE
>>> SearchQuerySet().exclude(personal_tags="london").filter(django_ct="people.userprofile")
[<SearchResult: people.userprofile (pk=u'1')>, <SearchResult: people.userprofile (pk=u'2')>, <SearchResult: people.userprofile (pk=u'3')>, <SearchResult: people.userprofile (pk=u'4')>, <SearchResult: people.userprofile (pk=u'5')>, <SearchResult: people.userprofile (pk=u'7')>, <SearchResult: people.userprofile (pk=u'8')>]
>>>

FIRST CASE QUERY TO SOLR
INFO: [] webapp=/solr path=/select/ params={fl=*+score&wt=json&start=0&q=((personal_tags:paris+AND+NOT+(personal_tags:london)))+AND+(django_ct:people.userprofile)&rows=20} hits=1 status=0 QTime=2

SECOND CASE QUERY TO SOLR
INFO: [] webapp=/solr path=/select/ params={fl=*+score&wt=json&start=0&q=(NOT+(personal_tags:london))+AND+(django_ct:people.userprofile)&rows=20} hits=0 status=0 QTime=1

THIRD CASE QUERY TO SOLR
INFO: [] webapp=/solr path=/select/ params={fl=*+score&wt=json&start=0&q=(NOT+(personal_tags:london)+AND+django_ct:people.userprofile)&rows=20} hits=7 status=0 QTime=2

Explanation
In the first case, I am searching for all user profiles with the tag "paris" and not the tag "london". This works fine and I get one result.

In the second case, I am searching for all user profies without the tag "london". I would expect to get at least as many results as in the first case, because this search is a superset of case one, but instead I get NO results. This is the bug.

In the third case, I have implemented the workaround. I have replaced the model statement with a filter statement. This works fine and I get the expected number of results. Note the only difference between the two queries sent to SOLR are the parenthesis after "london"

Relevant versions in use:
SOLR: 3.5.0
django-haystack: 1.2.6
django: 1.3.1