无法在 spring 引导 Hibernate Search Elasticsearch 中配置我自己的分析器

Impossible to configure my own analyzer in spring boot Hibernate Search Elasticsearch

请帮忙。很多天我都在尝试在我的 Spring 引导应用程序中配置 elasticsearch 索引,当然我在文档中遗漏了一些东西,但我没有找到什么。

我对 spring 比较陌生,几天后我发现它非常强大,这是我第一个很长的问题。

问题描述 我有一个简单的对象 Book 在我自己的分析器上用 @FullTextField 索引

@Entity
@Indexed
@Data
public class Book {
    @Id
    @GeneratedValue
    private Long id;

    @FullTextField(analyzer = "my_analyze_french")
    private String name;

用我的配置

package com.mycompany.jpa.elasticsearch;
import org.hibernate.search.backend.elasticsearch.analysis.ElasticsearchAnalysisConfigurationContext;
import org.hibernate.search.backend.elasticsearch.analysis.ElasticsearchAnalysisConfigurer;

// https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#getting-started-analysis
public class CVAnalysisConfigurer implements ElasticsearchAnalysisConfigurer {
    @Override
    public void configure(ElasticsearchAnalysisConfigurationContext context) {
        System.out.println("DEFINE a NEW ANALYZER");
        // define each analyzer + associated token filter parameters
        context.analyzer("my_analyze_french").custom()
                .tokenizer("standard")
                .tokenFilters("lowercase", "snowball_french", "asciifolding"); // warning order

        // stemmer for french : regroup words by family
        context.tokenFilter("snowball_french")
                .type("snowball")
                .param("language", "French");

        System.out.println("DEFINE a NEW ANALYZER:DONE");
    }
}

在我的 application.properties 中,我指明了要配置我的分析器的 bean 的名称

# cf https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#backend-elasticsearch-analysis
hibernate.search.backend.analysis.configurer=class:com.mycompany.jpa.elasticsearch.CVAnalysisConfigurer

当我启动我的应用程序时出现错误

2021-06-21 11:37:05.685 ERROR 17135 --- [port thread - 1] o.h.s.e.r.spi.RootFailureCollector       : HSEARCH000521: Hibernate Search encountered a failure during bootstrap; continuing for now to list all problems, but the process will ultimately be aborted.
Context: Hibernate ORM mapping, type 'com.mycompany.jpa.elasticsearch.Book'
Failure:

org.hibernate.search.util.common.SearchException: HSEARCH400007: Elasticsearch request failed: HSEARCH400090: Elasticsearch response indicates a failure.
Request: PUT /book-000001 with parameters {}
Response: 400 'Bad Request' from 'http://localhost:9200' with body 
{
  "error": {
    "root_cause": [
      {
        "type": "mapper_parsing_exception",
        "reason": "Failed to parse mapping [_doc]: analyzer [my_analyze_french] has not been configured in mappings"
      }
    ],
    "type": "mapper_parsing_exception",
    "reason": "Failed to parse mapping [_doc]: analyzer [my_analyze_french] has not been configured in mappings",
    "caused_by": {
      "type": "illegal_argument_exception",
      "reason": "analyzer [my_analyze_french] has not been configured in mappings"
    }
  },
  "status": 400
}

    at org.hibernate.search.backend.elasticsearch.work.impl.AbstractNonBulkableWork.handleResult(AbstractNonBulkableWork.java:84) ~[hibernate-search-backend-elasticsearch-6.0.4.Final.jar:6.0.4.Final]
    at org.hibernate.search.backend.elasticsearch.work.impl.AbstractNonBulkableWork.lambda$execute(AbstractNonBulkableWork.java:66) ~[hibernate-search-backend-elasticsearch-6.0.4.Final.jar:6.0.4.Final]
    at java.base/java.util.concurrent.CompletableFuture$UniApply.tryFire(CompletableFuture.java:642) ~[na:na]
    at java.base/java.util.concurrent.CompletableFuture.postComplete(CompletableFuture.java:506) ~[na:na]
    at java.base/java.util.concurrent.CompletableFuture.complete(CompletableFuture.java:2073) ~[na:na]
    at org.hibernate.search.backend.elasticsearch.client.impl.ElasticsearchClientImpl.onFailure(ElasticsearchClientImpl.java:127) ~[hibernate-search-backend-elasticsearch-6.0.4.Final.jar:6.0.4.Final]
    at org.elasticsearch.client.RestClient$FailureTrackingResponseListener.onDefinitiveFailure(RestClient.java:644) ~[elasticsearch-rest-client-7.13.2.jar:7.13.2]
    at org.elasticsearch.client.RestClient.completed(RestClient.java:386) ~[elasticsearch-rest-client-7.13.2.jar:7.13.2]
    at org.elasticsearch.client.RestClient.completed(RestClient.java:370) ~[elasticsearch-rest-client-7.13.2.jar:7.13.2]
    at org.apache.http.concurrent.BasicFuture.completed(BasicFuture.java:122) ~[httpcore-4.4.14.jar:4.4.14]
    at org.apache.http.impl.nio.client.DefaultClientExchangeHandlerImpl.responseCompleted(DefaultClientExchangeHandlerImpl.java:181) ~[httpasyncclient-4.1.4.jar:4.1.4]
    at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.processResponse(HttpAsyncRequestExecutor.java:448) ~[httpcore-nio-4.4.14.jar:4.4.14]
    at org.apache.http.nio.protocol.HttpAsyncRequestExecutor.inputReady(HttpAsyncRequestExecutor.java:338) ~[httpcore-nio-4.4.14.jar:4.4.14]
    at org.apache.http.impl.nio.DefaultNHttpClientConnection.consumeInput(DefaultNHttpClientConnection.java:265) ~[httpcore-nio-4.4.14.jar:4.4.14]
    at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:81) ~[httpasyncclient-4.1.4.jar:4.1.4]
    at org.apache.http.impl.nio.client.InternalIODispatch.onInputReady(InternalIODispatch.java:39) ~[httpasyncclient-4.1.4.jar:4.1.4]
    at org.apache.http.impl.nio.reactor.AbstractIODispatch.inputReady(AbstractIODispatch.java:114) ~[httpcore-nio-4.4.14.jar:4.4.14]
    at org.apache.http.impl.nio.reactor.BaseIOReactor.readable(BaseIOReactor.java:162) ~[httpcore-nio-4.4.14.jar:4.4.14]
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvent(AbstractIOReactor.java:337) ~[httpcore-nio-4.4.14.jar:4.4.14]
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.processEvents(AbstractIOReactor.java:315) ~[httpcore-nio-4.4.14.jar:4.4.14]
    at org.apache.http.impl.nio.reactor.AbstractIOReactor.execute(AbstractIOReactor.java:276) ~[httpcore-nio-4.4.14.jar:4.4.14]
    at org.apache.http.impl.nio.reactor.BaseIOReactor.execute(BaseIOReactor.java:104) ~[httpcore-nio-4.4.14.jar:4.4.14]
    at org.apache.http.impl.nio.reactor.AbstractMultiworkerIOReactor$Worker.run(AbstractMultiworkerIOReactor.java:591) ~[httpcore-nio-4.4.14.jar:4.4.14]
    at java.base/java.lang.Thread.run(Thread.java:829) ~[na:na]
Caused by: org.hibernate.search.util.common.SearchException: HSEARCH400090: Elasticsearch response indicates a failure.
    at org.hibernate.search.backend.elasticsearch.work.impl.DefaultElasticsearchRequestSuccessAssessor.checkSuccess(DefaultElasticsearchRequestSuccessAssessor.java:103) ~[hibernate-search-backend-elasticsearch-6.0.4.Final.jar:6.0.4.Final]
    at org.hibernate.search.backend.elasticsearch.work.impl.DefaultElasticsearchRequestSuccessAssessor.checkSuccess(DefaultElasticsearchRequestSuccessAssessor.java:86) ~[hibernate-search-backend-elasticsearch-6.0.4.Final.jar:6.0.4.Final]
    at org.hibernate.search.backend.elasticsearch.work.impl.AbstractNonBulkableWork.handleResult(AbstractNonBulkableWork.java:79) ~[hibernate-search-backend-elasticsearch-6.0.4.Final.jar:6.0.4.Final]
    ... 23 common frames omitted

2021-06-21 11:37:05.741 ERROR 17135 --- [           main] j.LocalContainerEntityManagerFactoryBean : Failed to initialize JPA EntityManagerFactory: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.search.util.common.SearchException: HSEARCH000520: Hibernate Search encountered failures during bootstrap. Failures:

    Hibernate ORM mapping: 
        type 'com.mycompany.jpa.elasticsearch.Book': 
            failures: 
              - HSEARCH400007: Elasticsearch request failed: HSEARCH400090: Elasticsearch response indicates a failure.
Request: PUT /book-000001 with parameters {}
Response: 400 'Bad Request' from 'http://localhost:9200' with body 
{
  "error": {
    "root_cause": [
      {
        "type": "mapper_parsing_exception",
        "reason": "Failed to parse mapping [_doc]: analyzer [my_analyze_french] has not been configured in mappings"
      }
    ],
    "type": "mapper_parsing_exception",
    "reason": "Failed to parse mapping [_doc]: analyzer [my_analyze_french] has not been configured in mappings",
    "caused_by": {
      "type": "illegal_argument_exception",
      "reason": "analyzer [my_analyze_french] has not been configured in mappings"
    }
  },
  "status": 400
}

2021-06-21 11:37:05.742  WARN 17135 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is javax.persistence.PersistenceException: [PersistenceUnit: default] Unable to build Hibernate SessionFactory; nested exception is org.hibernate.search.util.common.SearchException: HSEARCH000520: Hibernate Search encountered failures during bootstrap. Failures:

    Hibernate ORM mapping: 
        type 'com.mycompany.jpa.elasticsearch.Book': 
            failures: 
              - HSEARCH400007: Elasticsearch request failed: HSEARCH400090: Elasticsearch response indicates a failure.
Request: PUT /book-000001 with parameters {}
Response: 400 'Bad Request' from 'http://localhost:9200' with body 
{
  "error": {
    "root_cause": [
      {
        "type": "mapper_parsing_exception",
        "reason": "Failed to parse mapping [_doc]: analyzer [my_analyze_french] has not been configured in mappings"
      }
    ],
    "type": "mapper_parsing_exception",
    "reason": "Failed to parse mapping [_doc]: analyzer [my_analyze_french] has not been configured in mappings",
    "caused_by": {
      "type": "illegal_argument_exception",
      "reason": "analyzer [my_analyze_french] has not been configured in mappings"
    }
  },
  "status": 400
}

2021-06-21 11:37:05.743  INFO 17135 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2021-06-21 11:37:05.758  INFO 17135 --- [           main] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
2021-06-21 11:37:05.761  INFO 17135 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]

我的配置 我用的是spring Boot 2.3.11,我的数据库是h2

主要依赖项是

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <!-- for use of elastic search, automatic indexation with jpa -->
    <dependency>
        <groupId>org.hibernate.search</groupId>
        <artifactId>hibernate-search-mapper-orm</artifactId>
        <version>6.0.4.Final</version>
    </dependency>
    <dependency>
        <groupId>org.hibernate.search</groupId>
        <artifactId>hibernate-search-backend-elasticsearch</artifactId>
        <version>6.0.4.Final</version>
    </dependency>

我指定elasticsearch的版本

<properties>
    <elasticsearch.version>7.13.2</elasticsearch.version>
</properties>

我的服务器版本是一样的,我用一个简单的docker来测试,我在每次启动前从卷中删除节点

version: '3'
services:
  elasticsearchstudy:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.13.2
    container_name: elasticsearchstudy
    environment:
      - "discovery.type=single-node"
    volumes:
      - ./elasticsearch:/usr/share/elasticsearch/data:rw
    ports:
      - 9200:9200
    restart: unless-stopped

我尝试了什么? 为了避免 Spring Boot 可能出现的一些问题,我尝试推迟引导,但有或没有它都不会改变任何东西

@SpringBootApplication
@EnableJpaRepositories(bootstrapMode = BootstrapMode.DEFERRED)
public class HibernateSearchStudy {

我尝试在 Postman 上使用 REST API 配置我的分析,当我处理使用 REST API localhost:9200/book/_analyze 创建的新索引时可以分析文档但无法在我的应用程序索引 Book-000001 上执行此操作(我无法修改先前创建的索引的分析器)

首先,我尝试在 @DataJpaTest 中完成所有操作,但由于它无法正常工作(同样的错误),我现在尝试在将数据插入我的存储库的 CommandLineRunner 中对其进行测试,然后我进行搜索

我认为我的 ElasticsearchAnalysisConfigurer 初始化从未被调用(我放入 configure 的跟踪从未出现)。怎么做到的?

任何帮助将不胜感激!!

application.properties 是 Spring 引导配置文件,而不是 Hibernate Search 配置文件。您不能只在其中转储 Hibernate Search 属性。

相反,为您的 Hibernate Search 属性添加前缀 spring.jpa.properties.,以便 Spring Boot 将属性传递给 Hibernate ORM,Hibernate ORM 会将它们传递给 Hibernate Search。例如:

# cf https://docs.jboss.org/hibernate/stable/search/reference/en-US/html_single/#backend-elasticsearch-analysis
spring.jpa.properties.hibernate.search.backend.analysis.configurer=class:com.mycompany.jpa.elasticsearch.CVAnalysisConfigurer