简体   繁体   English

Django Haystack - 如何通过布尔字段过滤搜索结果?

[英]Django Haystack - How to filter search results by a boolean field?

Trying to filter a SearchQuerySet by a boolean value doesn't work for me. 尝试通过布尔值过滤SearchQuerySet对我来说不起作用。 (I am using the provided "Simple" backend search engine while testing.) (我在测试时使用提供的“简单”后端搜索引擎。)

I have an index like: 我有一个像这样的索引:

class MyIndex(indexes.SearchIndex, indexes.Indexable):
    text = indexes.CharField(document=True, use_template=True)
    has_been_sent = indexes.BooleanField(model_attr='has_been_sent')
    # other fields

    def get_model(self):
        return MyModel

And I use a custom form for the search: 我使用自定义表单进行搜索:

BOOLEAN_OPTIONS = [ ('either', 'Either'), ('yes', 'Yes'), ('no', 'No') ]

class MyModelSearchForm(SearchForm):
    # other fields
    has_been_sent = forms.ChoiceField( widget = forms.Select(), label = 'Sent?', choices=BOOLEAN_OPTIONS )

def search(self):
    sqs = super(MyModelSearchForm, self).search()

    if not self.is_valid(): return self.no_query_found()

    sqs = sqs.models(MyModel) # cuts out other models from the search results
    if self.cleaned_data['has_been_sent'] != 'either':
        if self.cleaned_data['has_been_sent'] == 'yes': sent = True
        else: sent = False
        sqs = sqs.filter(has_been_sent=sent)

    return sqs

If I set the has_been_sent option to Yes or No in the form, I always get 0 results, which is clearly wrong. 如果我在表单中将has_been_sent选项设置为Yes或No,我总是得到0结果,这显然是错误的。 I've also tried in the shell, with no luck. 我也试过shell,没有运气。 sqs.filter(has_been_sent=True) and sqs.filter(has_been_sent=False) both return an empty list, EVEN THOUGH sqs.values('has_been_sent') clearly shows a bunch of records with True values for has_been_sent. sqs.filter(has_been_sent=True)sqs.filter(has_been_sent=False)都返回一个空列表,即使sqs.values('has_been_sent')清楚地显示了一堆具有has_been_sent的True值的记录。 And even stranger, sqs.filter(has_been_sent='t') returns a subset of records, along with 'f', 'a', and unrelated letters like 'j'! 甚至更奇怪的是, sqs.filter(has_been_sent='t')返回记录的子集,以及'f','a'和不相关的字母,如'j'! I'm at a total loss. 我完全失去了。 Does anybody have experience with this sort of problem with Haystack? 有没有人有过Haystack这类问题的经验?

On a related note, are the fields you filter on through SearchQuerySet().filter() from the index fields (in search_indexes.py) or the model fields (in their respective models.py)? 在相关的说明中,您是通过SearchQuerySet().filter()来自索引字段(在search_indexes.py中)或模型字段(在各自的models.py中) SearchQuerySet().filter()的字段吗?

EDIT: 编辑:

I've been attempting to test my filters through Django's manage.py shell, but I think I'm doing it wrong. 我一直试图通过Django的manage.py shell测试我的过滤器,但我认为我做错了。 It doesn't seem to be following my search_indexes.py, since I limited it to a subset of MyModel with the index_queryset() method there, but I get ALL objects of MyModel in the shell. 它似乎没有跟随我的search_indexes.py,因为我将其限制为MyModel的子集,其中包含index_queryset()方法,但我在shell中获取了MyModel的所有对象。

>>> from haystack.query import SearchQuerySet
>>> from myapp.models import MyModel
>>> sqs = SearchQuerySet().models(MyModel)

And then some testing: 然后进行一些测试:

>>> len(sqs) # SHOULD be 5, due to the index_queryset() method I defined in search_indexes.py
17794
>>> sqs.filter(has_been_sent='true') # Same happens for True, 'TRUE', and all forms of false
[]
>>> len(sqs.filter(not_a_real_field='g')) # Made-up filter field, returns a subset somehow??
2591
>>> len(sqs.filter(has_been_sent='t'))
3621
>>> len(sqs.filter(has_been_sent='f'))
2812

Because I get a subset when filtering on the fake field, I don't think it's recognizing has_been_sent as one of my filter fields. 因为我在伪字段上过滤时得到了一个子集,我认为它不会将has_been_sent识别为我的过滤字段之一。 Especially since the results for 't' and 'f' don't add up to the total, which it SHOULD, as that boolean field is required for all records. 特别是因为't'和'f'的结果不等于总数,它应该是,因为所有记录都需要布尔字段。 Am I missing a step in my testing? 我在测试中错过了一步吗?

Try to filter as a string true or false in the query, this has been the known limitation in haystack and i am not sure if this is fixed, instead of doing: 尝试在查询中过滤为字符串truefalse ,这是haystack中已知的限制,我不确定这是否已修复,而不是:

sqs.filter(has_been_sent=True)

Do this: 做这个:

sqs.filter(has_been_sent='true') # true or false in lowercase

PS when you do SearchQuerySet().filter() you filter based on the fields defined in search_indexes.py file. 当您执行SearchQuerySet().filter()时,PS会根据search_indexes.py文件中定义的字段进行过滤。

It appears that the problem was in the Simple backend. 似乎问题出在Simple后端。 I installed and switched Haystack over to Whoosh, and this problem cleared up. 我安装并将Haystack切换到Whoosh,这个问题就解决了。 (Now SearchQuerySet().models() doesn't work, but that's apparently a documented bug with Haystack + Whoosh.) (现在SearchQuerySet()。models()不起作用,但这显然是Haystack + Whoosh的文档错误。)

Edit: Due to further troubles with Whoosh, I switched to using Solr 4.5.1 as my backend. 编辑:由于Whoosh的进一步麻烦,我转而使用Solr 4.5.1作为我的后端。 Everything is working as expected now. 现在一切都按预期工作了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM