如何通过 Elasticsearch 在 HibernateSearch 中突出显示

How to do highlighting within HibernateSearch over Elasticsearch

背景:我们正在将 java 应用程序从 Lucene 转换为 Elasticsearch 5.6.6。使用 Hibernate 5.2.11 和 Hibernate-Search 5.8.2。我们有许多自定义分析器,它们在 ES 中注册(根据 documentation 使用 ElasticsearchAnalysisDefinitionProvider),并将它们作为插件导入到 ES 服务器中。

对于基本查询,使用查询 DSL 似乎相当简单,但是有一段突出显示的代码我无法开始工作。

与直接处理 Lucene 相比,ES 中的分析器被移除了一些,这可能是我的主要问题之一。

这是我们需要获取的现有方法converted/working;当前在第 3 行中收到 NullPointerException 调用:...getAnalyzer(analyzerName),当它执行 SearchIntegration integration = integrations.get( LuceneEmbeddedIndexManagerType.INSTANCE )

时,我将其跟踪到 ImmutableSearchFactory::getAnalyzer
private boolean isMatch(String field, String target, String analyzerName, Query sourceQ, FullTextSession fts) {

    Analyzer analyzer = fts.getSearchFactory().getAnalyzer(analyzerName);

    Highlighter highlighter = new Highlighter(new QueryScorer(sourceQ, field));
    highlighter.setTextFragmenter(new NullFragmenter());

    try {
        String result = highlighter.getBestFragment(analyzer, field, target);
        return StringUtils.hasText(result);
    }
    catch (IOException e) {
        throw new IllegalStateException("Caught IOException while highlighting a String?..", e);
    }
    catch (InvalidTokenOffsetsException e) {
        throw new IllegalStateException("Caught InvalidTokenOffsetsException while highlighting a String?..", e);
    }
}

是否有其他获取分析器的方法或此处不正确的地方?
但更重要的是,在 ES 上使用 Hibernate Search 时如何突出显示片段?

Is there another way to get the analyzer or something incorrect here?

如果您为 Elasticsearch 定义了分析器,则无法获取 org.apache.lucene.analysis.Analyzer 的实例,因为在这种情况下,分析器仅存在于远程 Elasticsearch 集群上,而 Hibernate Search 从不​​直接使用分析器:它仅将分析器定义推送到 Elasticsearch,然后使用对该分析器(名称)的引用。

您要做的是使用仅存在于另一台服务器(ES 服务器)中的分析器来使用 Lucene 运行 在本地进行分析。这行不通。

But more importantly, how do you highlight a fragment when using Hibernate Search over ES?

Hibernate Search 本身不提供突出显示功能;只有 Lucene,运行 传统上落后于 Hibernate Search 的技术可以做到。当您使用 Elasticsearch 集成时,您正在将 Lucene 技术换成 Elasticsearch 技术(或多或少)。因此你必须以不同的方式做事。

休眠搜索 6.x

Hibernate Search 6.0.0.Beta3+ 提供了一个新的 API,让您可以更轻松地利用高级 Elasticsearch 功能。如果您想突出显示作为搜索查询的一部分,则无需再直接依赖 REST 客户端。

您可以使用 request transformer to add a highlight element to the HTTP request, then use the jsonHit projection 检索每个命中的 JSON,其中包含一个包含突出显示字段和突出显示片段的 highlight 元素。

休眠搜索 5.x

在 Hibernate Search 5.x 中,您无法访问搜索请求和响应的原始 JSON,因此需要另一种方法。

您可以选择继续使用 Lucene。为此,您必须定义完全相同的分析器,但要针对 Lucene。您可以使用与 Elasticsearch 几乎相同的方式使用 analysis definition provider。 然后你应该能够调用 getAnalyzer() 来检索 Lucene 分析器并使用 Lucene APIs.

执行突出显示

但有一个警告:如果您只使用 Elasticsearch 集成,Hibernate Search 默认会忽略 Lucene 分析器。强制 Hibernate Search 考虑 Lucene 配置的唯一方法是在您的一个实体上放置一个 @AnalyzerDef 注释,而不是在任何地方使用它。如果添加注释不是一个选项,您也可以使用编程映射来定义它。这很奇怪,我知道,但这是遗留行为。

另一种选择是向 Elasticsearch 发送 highlight 查询。但是,这将需要访问低级 APIs 以发送 JSON 查询,我什至不确定您是否可以使用 ES APIs 对任意对象执行突出显示一段文本(仅在索引文档中)。如果您想调查,一些有用的信息: