Hibernate Search:Elasticsearch 和 Lucene 产生不同的搜索结果
Hibernate Search: Elasticsearch and Lucene yield different search results
我正在尝试使用 Spring Data Rest 和 Hibernate Search 为我的 REST 后端实现一个非常基本的搜索功能。我想允许用户通过将查询字符串传递给搜索函数来执行任意查询。为了能够更轻松地 运行 本地后端并避免将 Elasticsearch 启动到 运行 测试,我希望能够在这些情况下使用本地索引。
我的问题是,与 Elasticsearch 相比,以下代码使用本地索引不会产生相同的结果。我试图将以下代码限制在我认为相关的范围内。
实体:
@Indexed(index = "MyEntity")
@AnalyzerDef(name = "ngram",
tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class ),
filters = {
@TokenFilterDef(factory = StandardFilterFactory.class),
@TokenFilterDef(factory = LowerCaseFilterFactory.class),
@TokenFilterDef(factory = StopFilterFactory.class),
@TokenFilterDef(factory = NGramFilterFactory.class,
params = {
@Parameter(name = "minGramSize", value = "2"),
@Parameter(name = "maxGramSize", value = "3") } )
}
)
public class MyEntity {
@NotNull
@Field(index = Index.YES, analyze = Analyze.YES, store = Store.YES, analyzer = @Analyzer(definition = "ngram"))
private String name;
@Field(analyze = Analyze.YES, store = Store.YES)
@FieldBridge(impl = StringCollectionFieldBridge.class)
@ElementCollection(fetch = FetchType.EAGER)
private Set<String> tags = new HashSet<>();
}
application.yml 本地索引:
spring:
jpa:
hibernate:
ddl-auto: update
show-sql: false
application.yml 对于 Elasticsearch:
spring:
jpa:
hibernate:
ddl-auto: create-drop
properties:
hibernate:
search:
default:
indexmanager: elasticsearch
elasticsearch:
host: 127.0.0.1:9200
required_index_status: yellow
搜索端点:
private static String[] FIELDS = { "name", "tags" };
@Override
public List<MyEntity> querySearch(String queryString) throws ParseException {
QueryParser queryParser = new MultiFieldQueryParser(FIELDS, new SimpleAnalyzer());
queryParser.setDefaultOperator(QueryParser.AND_OPERATOR);
org.apache.lucene.search.Query query = queryParser.parse(queryString);
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(this.entityManager);
javax.persistence.Query persistenceQuery =
fullTextEntityManager.createFullTextQuery(query, MyEntity.class);
return persistenceQuery.getResultList();
}
我使用以下值创建了一个 MyEntity 实例:
$ curl 'localhost:8086/myentities'
{
"_embedded" : {
"myentities" : [ {
"name" : "Test Entity",
"tags" : [ "bar", "foobar", "foo" ],
"_links" : {
...
}
} ]
},
"_links" : {
...
}
}
以下查询(return 该实体)使用 Elasticsearch 有效:
- 名称:测试
- 名称:实体
- 标签:栏
使用本地索引,我得到了“tags:bar: 的结果:但是名称字段上的查询 return 不是结果。知道为什么会这样吗?
您应该确保 Elasticsearch 映射是由 Hibernate Search 正确创建的。默认情况下,Hiberante Search 只会在映射缺失时创建映射。
如果您启动应用程序一次,然后更改映射并再次启动应用程序,可能 name
字段在 Elasticsearch 中不正确。
在开发模式下,试试这个:
spring:
jpa:
hibernate:
ddl-auto: create-drop
properties:
hibernate:
search:
default:
indexmanager: elasticsearch
elasticsearch:
host: 127.0.0.1:9200
required_index_status: yellow
index_schema_management_strategy: drop-and-create-and-drop
请注意,不幸的是,文档被成功索引并不表示您的映射是正确的:当您尝试索引未知字段并试图猜测它们的类型时,Elasticsearch 甚至会动态创建字段(在文本字段的情况下通常是错误的。 ..).您可以使用 validate
索引管理策略来真正确保在 bootstrap 上 Elasticsearch 映射与 Hibernate Search 同步。
我正在尝试使用 Spring Data Rest 和 Hibernate Search 为我的 REST 后端实现一个非常基本的搜索功能。我想允许用户通过将查询字符串传递给搜索函数来执行任意查询。为了能够更轻松地 运行 本地后端并避免将 Elasticsearch 启动到 运行 测试,我希望能够在这些情况下使用本地索引。
我的问题是,与 Elasticsearch 相比,以下代码使用本地索引不会产生相同的结果。我试图将以下代码限制在我认为相关的范围内。
实体:
@Indexed(index = "MyEntity")
@AnalyzerDef(name = "ngram",
tokenizer = @TokenizerDef(factory = StandardTokenizerFactory.class ),
filters = {
@TokenFilterDef(factory = StandardFilterFactory.class),
@TokenFilterDef(factory = LowerCaseFilterFactory.class),
@TokenFilterDef(factory = StopFilterFactory.class),
@TokenFilterDef(factory = NGramFilterFactory.class,
params = {
@Parameter(name = "minGramSize", value = "2"),
@Parameter(name = "maxGramSize", value = "3") } )
}
)
public class MyEntity {
@NotNull
@Field(index = Index.YES, analyze = Analyze.YES, store = Store.YES, analyzer = @Analyzer(definition = "ngram"))
private String name;
@Field(analyze = Analyze.YES, store = Store.YES)
@FieldBridge(impl = StringCollectionFieldBridge.class)
@ElementCollection(fetch = FetchType.EAGER)
private Set<String> tags = new HashSet<>();
}
application.yml 本地索引:
spring:
jpa:
hibernate:
ddl-auto: update
show-sql: false
application.yml 对于 Elasticsearch:
spring:
jpa:
hibernate:
ddl-auto: create-drop
properties:
hibernate:
search:
default:
indexmanager: elasticsearch
elasticsearch:
host: 127.0.0.1:9200
required_index_status: yellow
搜索端点:
private static String[] FIELDS = { "name", "tags" };
@Override
public List<MyEntity> querySearch(String queryString) throws ParseException {
QueryParser queryParser = new MultiFieldQueryParser(FIELDS, new SimpleAnalyzer());
queryParser.setDefaultOperator(QueryParser.AND_OPERATOR);
org.apache.lucene.search.Query query = queryParser.parse(queryString);
FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(this.entityManager);
javax.persistence.Query persistenceQuery =
fullTextEntityManager.createFullTextQuery(query, MyEntity.class);
return persistenceQuery.getResultList();
}
我使用以下值创建了一个 MyEntity 实例:
$ curl 'localhost:8086/myentities'
{
"_embedded" : {
"myentities" : [ {
"name" : "Test Entity",
"tags" : [ "bar", "foobar", "foo" ],
"_links" : {
...
}
} ]
},
"_links" : {
...
}
}
以下查询(return 该实体)使用 Elasticsearch 有效:
- 名称:测试
- 名称:实体
- 标签:栏
使用本地索引,我得到了“tags:bar: 的结果:但是名称字段上的查询 return 不是结果。知道为什么会这样吗?
您应该确保 Elasticsearch 映射是由 Hibernate Search 正确创建的。默认情况下,Hiberante Search 只会在映射缺失时创建映射。
如果您启动应用程序一次,然后更改映射并再次启动应用程序,可能 name
字段在 Elasticsearch 中不正确。
在开发模式下,试试这个:
spring:
jpa:
hibernate:
ddl-auto: create-drop
properties:
hibernate:
search:
default:
indexmanager: elasticsearch
elasticsearch:
host: 127.0.0.1:9200
required_index_status: yellow
index_schema_management_strategy: drop-and-create-and-drop
请注意,不幸的是,文档被成功索引并不表示您的映射是正确的:当您尝试索引未知字段并试图猜测它们的类型时,Elasticsearch 甚至会动态创建字段(在文本字段的情况下通常是错误的。 ..).您可以使用 validate
索引管理策略来真正确保在 bootstrap 上 Elasticsearch 映射与 Hibernate Search 同步。