【问题标题】:Django Haystack - How to filter search results by a boolean field?Django Haystack - 如何通过布尔字段过滤搜索结果?
【发布时间】:2013-10-07 20:46:16
【问题描述】:

尝试通过布尔值过滤 SearchQuerySet 对我不起作用。 (我在测试时使用提供的“简单”后端搜索引擎。)

我有一个类似的索引:

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

我使用自定义表单进行搜索:

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

如果我在表单中将 has_been_sent 选项设置为 Yes 或 No,我总是得到 0 个结果,这显然是错误的。我也尝试过shell,但没有运气。 sqs.filter(has_been_sent=True)sqs.filter(has_been_sent=False) 都返回一个空列表,即使 sqs.values('has_been_sent') 清楚地显示了一堆 has_been_sent 值为 True 的记录。更奇怪的是,sqs.filter(has_been_sent='t') 返回记录的子集,以及“f”、“a”和不相关的字母,如“j”!我完全不知所措。有没有人遇到过 Haystack 的这类问题?

在相关说明中,您是从索引字段(在 search_indexes.py 中)还是模型字段(在它们各自的 models.py 中)通过 SearchQuerySet().filter() 过滤的字段?

编辑:

我一直在尝试通过 Django 的 manage.py shell 测试我的过滤器,但我认为我做错了。它似乎没有跟随我的 search_indexes.py,因为我在那里使用 index_queryset() 方法将它限制为 MyModel 的一个子集,但我在 shell 中获得了 MyModel 的所有对象。

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

然后进行一些测试:

>>> 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

因为我在过滤虚假字段时得到了一个子集,所以我认为它不会将 has_been_sent 识别为我的过滤器字段之一。特别是因为 't' 和 'f' 的结果加起来不等于总数,这是应该的,因为所有记录都需要该布尔字段。我在测试中错过了一步吗?

【问题讨论】:

    标签: python django django-haystack


    【解决方案1】:

    尝试在查询中过滤为字符串 truefalse,这是 haystack 中的已知限制,我不确定这是否已修复,而不是这样做:

    sqs.filter(has_been_sent=True)
    

    这样做:

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

    P.S 当您执行 SearchQuerySet().filter() 时,您会根据 search_indexes.py 文件中定义的字段进行过滤。

    【讨论】:

    • 嗯。我仍然得到一个“真”和“假”的空结果。我想我一定是通过manage.py shell 测试错了。我编辑了我的主要帖子以显示我是如何测试的。我想我一定是错过了一步。
    • 我建议你在模型或search_indexes.py文件中为布尔字段添加一个默认值,然后分别运行命令rebuild_index和update_index,并按照我的建议再次测试。
    【解决方案2】:

    看来问题出在 Simple 后端。我安装了 Haystack 并将其切换到 Whoosh,这个问题就解决了。 (现在 SearchQuerySet().models() 不起作用,但这显然是 Haystack + Whoosh 的记录错误。)

    编辑:由于 Whoosh 的进一步问题,我转而使用 Solr 4.5.1 作为我的后端。现在一切正常。

    【讨论】:

      猜你喜欢
      • 2021-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-14
      • 1970-01-01
      • 2011-01-10
      • 2020-04-07
      • 2014-03-15
      相关资源
      最近更新 更多