我目前正在 Django 上构建 webapp,它使用 Haystack 和 ElasticSearch 来实现搜索。我成功地设置了它,但现在我正在努力实现正确的搜索结果顺序。
我使用默认的 es 后端实现,搜索的文档包括游戏名称、俄罗斯游戏名称和描述:
text = indexes.CharField(document=True, use_template=True)
#Document
{{ object.name }}
{{ object.name_ru }}
{{ object.description }}
我从以下查询中获得 SearchResult:
sqs=SearchQuerySet().models(Game).load_all()\
.filter(content__startswith=query)
结果是预期的结果,而不是期望的结果。例如,如果我按“adv”搜索,结果是:
- 使命召唤:高级 war
- 胖公主历险记
- 冒险时间:芬恩和 jack 调查
- Fairy Fencer F: Advent Dark Force
我想要的是按游戏名称中单词(以查询开头)的位置排序的结果,因此示例结果应如下所示:
- 冒险时间:芬恩和 jack 调查
- 胖公主历险记
- 使命召唤:高级 war
- Fairy Fencer F: Advent Dark Force
拜托,有人可以指出我如何实现这一目标。提前致谢!
更新!!! 请参阅下面我的解决方案。
最佳答案
解决了。 部分答案在此处找到:stackoverflow.com/questions/27538766/scoring-by-term-position-in-elasticsearch - 解释了如何重写评分以考虑术语位置并构建查询以按该分数排序。
结果是,要使其与 Django-Haystack 一起使用,您需要覆盖 Haystack 提供的 Elasticsearch Backend 和 SearchQuerySet。下面是我对此的实现。
首先,Haystack需要的是:
像这样生成正确的映射:
"text" : { "type" : "string", "index_options" : "offsets", "index_analyzer" : "edgengram_analyzer", "search_analyzer" : "standard_search" }
当“index_options”设置为“offsets”时——术语偏移量保存在索引中,以便我们稍后在评分脚本中检索它。
构建按更新分数排序的查询。我的查询如下所示:
{"query":{ "match_phrase_prefix" : {"text" : text} }, "sort": { "_script": { "script_file": "score_script", "type":"number", "order": "asc", "params": {"q": text} } } }
提供更新分数的脚本文件“score_script”如下所示:
termInfo=_index["text"].get(q,_OFFSETS | _CACHE); for(pos in termInfo) { return _score+pos.startOffset };
所以首先要做的是。为了构建正确的映射,我们需要覆盖 Haystack 提供的 ElasticSearch 后端,这样我们就可以传递自定义参数,如“index_options”。我的实现基于 elasticstack——允许为每个字段指定自定义分析器的项目,如下所示:
text = CharField(document=True, use_template=True,
analyzer='stop')
这是我对 elasticstack 可配置后端的定制——gist.github.com/GrigoriyMikhalkin/f76be703bc53380986a0#file-backend-py。它添加了 'add' 参数,该参数接受形式字典 -- {parameter: value}。示例:
text = CharField(document=True, use_template=True,
analyzer="edgengram_analyzer",\
add={"search_analyzer":"standard_search",
"index_options":"offsets"})
要使用它,您需要像这样覆盖旅游项目的 settings.py 中的 HAYSTACK_CONNECTIONS 变量:
HAYSTACK_CONNECTIONS = {
"default":{
"ENGINE":
"base.search_backend.backend.ConfigurableElasticSearchEngine",
"URL": os.getenv("ELASTICSEARCH_URL", "http://127.0.0.1:9200/"),
"INDEX_NAME": "haystack",
}
有关详细信息,请参阅 elasticstack 文档。
下一步是构建正确的查询。它由两部分组成。首先,您需要创建重新评分的脚本(如上面的脚本)并将其放置在 ES 的/config/scripts/目录中。
下一步是覆盖 Haystack 提供的默认 SearchQuerySet。我的实现受到这篇博文的启发: http://www.stamkracht.com/extending-haystacks-elasticsearch-backend/
我的实现 (gist.github.com/GrigoriyMikhalkin/f76be703bc53380986a0#file-query-py) 将 custom_search 方法添加到 SearchQuerySet。可以这样使用:
sqs = ConfigurableSearchQuerySet().models(Game).load_all()\
.filter(content__startswith=q)\
.custom_search(search_text=q)
关于python - Django Haystack Elasticsearch : order by position of matched term,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33789024/