我在我的 java 应用程序中使用 Hibernate search 6 Lucne 后端。
我正在执行各种搜索操作,包括模糊搜索。
我获得搜索结果,没有任何问题。
现在我想展示在结果列表中选择每个结果的原因是什么。
假设搜索关键字是“test”,在“name”、“description”、“Id”等字段中进行模糊搜索。我在列表中得到了 10 个结果。现在我想突出显示每个结果的字段中的值,这些值导致该结果成为匹配结果。
eg:将以下内容视为搜索结果 List 对象中的项目之一。 (为了清楚起见,我将其编写为 JSON 格式)
{
name:"ABC some test name",
description: "this is a test element",
id: "abc123"
}
结果表明它被选为搜索结果,因为关键字“test”同时出现在“名称”和“描述”字段中。当我显示搜索结果时,我想在前端突出显示这些特定字段。
目前,我正在通过 java REST API 将搜索结果检索到我的 Angular 前端。如何在我的 java 应用程序中使用 Hibernate search 6 获取这些特定字段及其值?
到目前为止,我已经浏览了 Hibernate search 6 文档,但一无所获。 (https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#preface)过去一周还查看了网络上似乎相关的问题,但没有得到任何结果远的。看来我的要求有点具体,这就是为什么我需要你的帮助。
Hibernate Search 中尚未实现突出显示,请参阅 HSEARCH-2192。 => 从 Hibernate Search 6.2 开始,它已实现!请参阅https://hibernate.org/search/releases/6.2/#search-highlighting,https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#search- dsl-突出显示
旧答案:
话虽这么说,您可以利用本机 Elasticsearch / Lucene API。
使用 Elasticsearch 相对简单:您可以使用 请求转换器 将
highlight
元素添加到 HTTP 请求,然后使用 jsonHit
投影 检索每个命中的 JSON,其中包含 highlight
元素,包括突出显示的字段和突出显示的片段。
使用 Lucene 会更复杂,并且您必须依赖不受支持的功能,但这是可行的。
从 Hibernate Search 谓词中检索 Lucene
Query
:
SearchPredicate predicate = ...;
Query query = LuceneMigrationUtils.toLuceneQuery(predicate);
然后进行突出显示:Hibernate 搜索突出显示未分析的字段 可能会有所帮助,因此该代码使用旧版本的 Lucene,您可能需要对其进行调整:
String highlightText(Query query, Analyzer analyzer, String fieldName, String text) {
QueryScorer queryScorer = new QueryScorer(query);
SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<span>", "</span>");
Highlighter highlighter = new Highlighter(formatter, queryScorer);
return highlighter.getBestFragment(analyzer, fieldName, text);
}
您需要向
org.apache.lucene:lucene-highlighter
添加依赖关系。
要检索分析器,请使用 Hibernate Search 元数据:https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#backend-lucene-access-analyzers
那么,将这些点连接起来......类似的事情吗?
Highlighter createHighlighter(SearchPredicate predicate, SearchScope<?> scope) {
// Taking a shortcut here to retrieve the index manager,
// since we already have the scope
// WARNING: This only works when searching a single index
Analyzer analyzer = scope.includedTypes().iterator().next().indexManager()
.unwrap( LuceneIndexManager.class )
.searchAnalyzer();
// WARNING: this method is not supported and might disappear in future versions of HSearch
Query query = LuceneMigrationUtils.toLuceneQuery(predicate);
QueryScorer queryScorer = new QueryScorer(query);
SimpleHTMLFormatter formatter = new SimpleHTMLFormatter("<span>", "</span>");
return new Highlighter(formatter, queryScorer);
}
SearchSession searchSession = Search.session( entityManager );
SearchScope<Book> scope = searchSession.scope( Book.class );
SearchPredicate predicate = scope.predicate().match()
.fields( "title", "authors.name" )
.matching( "refactoring" )
.toPredicate();
Highlighter highlighter = createHighlighter(predicate, scope);
// Using Pair from Apache Commons, but others would work just as well
List<Pair<Book, String>> hits = searchSession.search( scope )
.select( select( f -> f.composite(
// Highlighting the title only, but you can do the same for other fields
book -> Pair.of( book, highlighter.getBestFragment(analyzer, "title", book.getTitle()))
f.entity()
) )
.where( predicate )
.fetch( 20 );
不确定是否可以编译,但这应该可以帮助您开始。
相关但不完全是您所要求的,有一个
explain
功能可以了解为什么给定的命中具有给定的分数:https://docs.jboss.org/hibernate/stable/search/参考/en-US/html_single/#search-dsl-query-explain