我来翻译一下:
问题已经解决。
部分答案可以在此找到:stackoverflow.com/questions/27538766/scoring-by-term-position-in-elasticsearch -- 这里解释了如何重写评分以考虑术语位置,并构建查询以按该得分排序。
所需的是,为了使其与Django-Haystack配合使用,需要覆盖Haystack提供的Elasticsearch后端和SearchQuerySet。以下是我实现这一点的方式。
首先,从Haystack中需要的是:
Produce correct mapping like this:
"text" : {
"type" : "string",
"index_options" : "offsets",
"index_analyzer" : "edgengram_analyzer",
"search_analyzer" : "standard_search"
}
When "index_options" set to "offsets" -- term offset saved in index so we can retrieve it later in scoring script.
Build query that sorts by updated score. My query looked like this:
{"query":{
"match_phrase_prefix" : {"text" : text}
},
"sort": {
"_script": {
"script_file": "score_script",
"type":"number",
"order": "asc",
"params": {"q": text}
}
}
}
Script file "score_script" that provides updated scores looks like this:
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)为SearchQuerySet添加了custom_search方法。它可以像这样使用:
sqs = ConfigurableSearchQuerySet().models(Game).load_all()\
.filter(content__startswith=q)\
.custom_search(search_text=q)
My custom ElasticSearch Backend.
script_file
存储在哪里了。请尝试将其保存在/etc/elasticsearch/scripts
或/etc/elasticsearch/config/scripts/
中。此外,script
选项也可用,因此您可以直接将代码放入查询中。 - Grigoriy Mikhalkin