Django Haystack-使用SearchQuerySet()通过字段的子字符串进行过滤

Django Haystack-使用SearchQuerySet()通过字段的子字符串进行过滤,django,django-haystack,Django,Django Haystack,我有一个Django项目,它使用SOLR进行索引 我正在尝试使用Haystack的SearchQuerySet类进行子字符串搜索 例如,当用户搜索术语“ear”时,它应该返回具有值为:“Search”的字段的条目。 如您所见,“ear”是“Search”的子字符串。(显然:) 换句话说,在一个完美的Django世界中,我想要的是: SearchQuerySet().all().filter(some_field__contains_substring='ear') 在SearchQuerySe

我有一个Django项目,它使用SOLR进行索引

我正在尝试使用Haystack的SearchQuerySet类进行子字符串搜索

例如,当用户搜索术语“ear”时,它应该返回具有值为:“Search”的字段的条目。 如您所见,“ear”“Search”的子字符串。(显然:)

换句话说,在一个完美的Django世界中,我想要的是:

SearchQuerySet().all().filter(some_field__contains_substring='ear')
SearchQuerySet()的haystack文档中, 它表示仅支持以下字段查找类型:

  • 包含
  • 精确的
  • gt,gte,lt,lte
  • 开始
  • 射程
我尝试使用\uuu contains,但它的行为与\uu exact完全相同,它查找句子中的确切单词(整个单词),而不是单词的子字符串

我很困惑,因为这样的功能非常基本,我不确定我是否遗漏了什么,或者是否有其他方法来解决这个问题(使用Regex或其他什么?)

感谢您使用以下字段可以完成此操作:

然后,对于部分匹配:

SearchQuerySet().all().filter(some_field='ear')

这是大海捞针

正如您所说,
\uuuuuu-exact
的实现方式与
\uuuuu-contains
完全相同,因此此功能在haystack中并不存在

修复程序正在此处等待合并:

您可以通过以下方式缩短固定版本的等待时间:

from haystack.inputs import BaseInput, Clean


class CustomContain(BaseInput):
    """
    An input type for making wildcard matches.
    """
    input_type_name = 'custom_contain'

    def prepare(self, query_obj):
        query_string = super(CustomContain, self).prepare(query_obj)
        query_string = query_obj.clean(query_string)

        exact_bits = [Clean(bit).prepare(query_obj) for bit in query_string.split(' ') if bit]
        query_string = u' '.join(exact_bits)

        return u'*{}*'.format(query_string)

# Usage:
SearchQuerySet().filter(content=CustomContain('searchcontentgoeshere'))

非常感谢。你的答案不是100%正确,但它引导我走向正确的方向。解决方案是使用NgramField,而不是EdgeNgramField,如下所示:
some\u field=index.NgramField(model\u attr='some\u field')
。EdgeNgram字段只能执行“以开头”和“以结尾”类型的过滤。我没有使用Solr,但使用ElastiSearch为我工作的Ngram字段。EdgeNgram字段的工作方式不同于
\uuuuContains
,它通过词干分析并根据词干查找其他匹配项,因此它将产生比contains更模糊的结果集。
from haystack.inputs import BaseInput, Clean


class CustomContain(BaseInput):
    """
    An input type for making wildcard matches.
    """
    input_type_name = 'custom_contain'

    def prepare(self, query_obj):
        query_string = super(CustomContain, self).prepare(query_obj)
        query_string = query_obj.clean(query_string)

        exact_bits = [Clean(bit).prepare(query_obj) for bit in query_string.split(' ') if bit]
        query_string = u' '.join(exact_bits)

        return u'*{}*'.format(query_string)

# Usage:
SearchQuerySet().filter(content=CustomContain('searchcontentgoeshere'))