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

https://docs.jboss.org/hibernate/search/5.11/reference/en-US/html_single/#elasticsearch-schema-management-strategy

请注意,不幸的是,文档被成功索引并不表示您的映射是正确的:当您尝试索引未知字段并试图猜测它们的类型时,Elasticsearch 甚至会动态创建字段(在文本字段的情况下通常是错误的。 ..).您可以使用 validate 索引管理策略来真正确保在 bootstrap 上 Elasticsearch 映射与 Hibernate Search 同步。