2

我们使用 Haystack 1.2.7 和 Whoosh 2.4.1 作为后端索引了大约 9k 个文档。尽管使用了 Haystack,但它看起来像是一个 Whoosh 问题。看看我的调试案例:

1) 如果我只是进行精确查找,Whoosh 会找到我的文档(如下所示):

>>> SearchQuerySet().all().models(PedidoSaida).filter(numero__exact='6210202443/10')
[<SearchResult: logistica.pedidosaida (pk=u'6')>]

2) 如果我只是运行startswith 查找,Whoosh 找不到我的文档(如下所示):

>>> SearchQuerySet().all().models(PedidoSaida).filter(numero__startswith='6210202443/10')
[]

3) 如果我将所有内容放在一个 OR 查询中,Whoosh 仍然找不到我的文档(如下所示):

>>> SearchQuerySet().all().models(PedidoSaida).filter(SQ(numero__exact='6210202443/10') | SQ(numero__startswith='6210202443/10'))
[]

查看 Haystack 发送给 Whoosh 的查询,我们有:

>>> str(SearchQuerySet().all().models(PedidoSaida).filter(numero__exact='6210202443/10').query)                                       
'(numero:6210202443/10) AND (django_ct:logistica.pedidosaida)'

>>> str(SearchQuerySet().all().models(PedidoSaida).filter(numero__startswith='6210202443/10').query)
'(numero:6210202443/10*) AND (django_ct:logistica.pedidosaida)'

>>> str(SearchQuerySet().all().models(PedidoSaida).filter(SQ(numero__exact='6210202443/10') | SQ(numero__startswith='6210202443/10')).query)
'((numero:6210202443/10 OR numero:6210202443/10*)) AND (django_ct:logistica.pedidosaida)'

如您所见,最后一个查询正是(第一个或第二个)。Whoosh 不应该找到我的文件吗?我看不出我的逻辑哪里错了:我使用的是 OR 并且发现比使用其中一个语句时要少。

我也认为 Whoosh 在第一个查询 (numero:6210202443/10) 中找到我的文档,但在第二个 (numero:6210202443/10*) 中没有找到我的文档,这很奇怪。但我想这与 Haystack 在我的 CharField 中使用的 StemmingAnalyzer 有关。之后我会深入研究一下。

4

2 回答 2

1

您可以QueryParser直接使用 a 查看 Whoosh 是如何解析该查询的:

>>> from whoosh.qparser import QueryParser
>>> QueryParser("content", schema=None).parse('((numero:6210202443/10 OR numero:6210202443/10*)) AND (django_ct:logistica.pedidosaida)')
And([Or([Term('numero', '6210202443/10'), Term('numero', '6210202443/')]), Prefix('content', '10'), Term('django_ct', 'logistica.pedidosaida')])

让我们重新格式化最后一行:

And([
    Or([
        Term('numero', '6210202443/10'),
        Term('numero', '6210202443/'),
    ]),
    Prefix('content', '10'),
    Term('django_ct', 'logistica.pedidosaida'),
])

因此,它看起来*/您的搜索词中的绑定更紧密。当然,我可以将其视为嗖嗖声中的错误。(我相信维护者会喜欢你的补丁☺)

想到的解决方法:

  1. 自己构建查询,而不是通过 Whoosh 的模糊定义和面向人的查询语言来回往返。当然,只有当您的索引在同一台机器上并且您正在使用相同的过程读取它时,这才有效;我对干草堆了解不多。

  2. 避免在numero字段中使用斜线。将它们更改为不太可能看起来像查询语法的东西,比如下划线。

  3. 进行前缀搜索时避免包含斜杠;例如,6210202443*在查询中的任何地方都可以正常工作。

于 2013-02-28T01:04:58.963 回答
0

按照@Eevee 的想法,我做了一些测试。检查这个:

>>> QueryParser("content", schema=None).parse('((numero:6210202443/10 OR (numero:6210202443/10*))) AND (django_ct:logistica.pedidosaida)')
And([
    Or([
        Term('numero', '6210202443/10'), 
        And([
            Term('numero', '6210202443/'), 
            Prefix('content', '10')
        ])
    ]), 
    Term('django_ct', 'logistica.pedidosaida')
])

似乎/优先于OR. 是否有意义?我认为逻辑运算符应该具有最高优先级。你同意吗?

如果这种行为是正确的,我猜这是 Haystack 查询生成器中的一个错误。不是吗?

我想贡献一个补丁,但我不确定它是否真的是解析器中的一个错误。取决于更有意义的优先级。

于 2013-03-01T02:06:36.973 回答