在单个合并结果ElasticSearch中统一所有突出显示结果

时间:2018-05-07 16:53:29

标签: elasticsearch highlight elasticsearch-percolate

我们正在使用Elasticsearch percolator。

我们尝试在单个文本中显示所有突出显示的项目,但没有获得许多不同的结果。但据我们所知,目前的ElasticSearch版本无法做到这一点。虽然我们found可以通过使用(升级版本)Lucene来实现这一点,因为它支持统一的突出显示结果,但我们没有时间。

我们需要快速简单的想法来解决这个问题。我们发现这可以通过添加相应的html装饰来完成,但我们正考虑列出每个结果的每个单词,然后使用该列表查找原始文本中的所有项目order结果显示在它们的位置

问题是,在单个合并结果中统一所有ElasticSearch突出显示结果的核心和更简单的流程是什么?

谢谢

1 个答案:

答案 0 :(得分:0)

完成小项目后,我们选择了python方法。

主要问题是ElasticSearch提供突出显示结果的方式:它是专为搜索引擎设计的,因此在文本片段与突出显示的结果之间,而不是提供完整的文本。

出于这个原因,我们选择通过后处理而不是使用ElasticSearch的荧光笔来突出显示结果:我们获取搜索结果,我们通过python处理它们,最后我们提供带有突出显示的单词的完整文本。

首先,获取querysearch结果的函数:

def get_response(client, index, query):
    s = Search().using(client).index(index).query("percolate", field='query', document={'title': query})
    response = s.execute()
    # get all matches: s.scan() https://elasticsearch-dsl.readthedocs.io/en/latest/search_dsl.html#pagination
    return response

Percolator是当前elasticsearch-dsl-py发行版中不存在的类,因此,现在我们实现它:

class Percolate(Query):
    name = 'percolate'

其次,我们获得所有条款及其文件ID:

def get_highlighted_term(response):
    dic_results = defaultdict(list)
    for hit in response:
        for query in hit.query:
            if query == 'span_term':
                dic_results[hit.query.span_term.title].append(hit.doc_id)
            if query == 'span_near':
                phrase = ''
                for title in hit.query.span_near.clauses:
                    phrase += title.span_term.title + ' '
                dic_results[phrase[:-1]].append(hit.doc_id)
    return dic_results

我们使用字典来实现其多功能性:标题/术语作为键,文档的标识符作为其值;这样可以更容易在文本突出显示期间获取相应的值。

最后,我们得到结果文本:

def get_highlighted_text(dic_results, text):
    for term, doc_ids in dic_results.items():
        insensitive_term = re.compile(re.escape(term), re.IGNORECASE)
        if len(doc_ids) > 1:
            result_text = "<ul id='multiple-links'>"
            for doc_id in doc_ids:
                result_text += "<li><a href='http://localhost/{0}'>{1}</a></li>".format(doc_id, term)
            result_text += "</ul>"
            text = insensitive_term.sub(result_text, text)
        else:
            text = insensitive_term.sub('<a href="http://localhost/{}">\g<0></a>'.format(doc_ids[0]), text)
    return text

这次我们将常用术语的文档ID作为下拉列表处理。我们还使用正则表达式进行替换。

这是我们的方法,您可以找到完整的项目代码here