背景
使用co.elastic.clients基于Elasticsearch API 正式文档,不会因版本不一致出现诸多问题,如jar报冲突等,可兼容SpringBoot1.X、2.x。


Maven依赖
  <dependency>
      <groupId>org.projectlombok</groupId>
      <artifactId>lombok</artifactId>
      <version>1.18.0</version>
  </dependency>

  <!-- ES 核心包 -->
  <dependency>
      <groupId>co.elastic.clients</groupId>
      <artifactId>elasticsearch-java</artifactId>
      <version>8.1.2</version>
  </dependency>

  <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-aop</artifactId>
      <version>1.5.4.RELEASE</version>
  </dependency>

  <dependency>
      <groupId>org.apache.httpcomponents</groupId>
      <artifactId>httpclient</artifactId>
      <version>4.5.13</version>
  </dependency>

  <dependency>
      <groupId>org.glassfish</groupId>
      <artifactId>jakarta.json</artifactId>
      <version>2.0.1</version>
  </dependency>

  <dependency>
      <groupId>com.alibaba</groupId>
      <artifactId>fastjson</artifactId>
      <version>1.2.7</version>
  </dependency>

  <dependency>
      <groupId>cn.hutool</groupId>
      <artifactId>hutool-all</artifactId>
      <version>5.0.6</version>
  </dependency>

  <dependency>
      <groupId>com.github.yangtu222</groupId>
      <artifactId>BeanUtils</artifactId>
      <version>1.0.9</version>
  </dependency>

客户端配置
非加密模式

@Data
@Configuration
@ConfigurationProperties(prefix = "elasticsearch")
public class ElasticSearchConfig{

    private String host;
    private Integer port;

    @Bean
    public ElasticsearchClient elasticsearchClient(){
        RestClient client = RestClient.builder(new HttpHost(host, port,"http")).build();
        ElasticsearchTransport transport = new RestClientTransport(client,new JacksonJsonpMapper());
        return new ElasticsearchClient(transport);
    }

加密模式


@Bean
public ElasticsearchClient elasticsearchClient(){
    ElasticsearchTransport transport = getElasticsearchTransport();
    return new ElasticsearchClient(transport);
}

@Bean
public ElasticsearchAsyncClient elasticsearchAsyncClient(){
    ElasticsearchTransport transport = getElasticsearchTransport();
    return new ElasticsearchAsyncClient(transport);
}

private ElasticsearchTransport getElasticsearchTransport() {
    // Create the low-level client
    final CredentialsProvider credentialsProvider =
            new BasicCredentialsProvider();
    credentialsProvider.setCredentials(AuthScope.ANY,
            new UsernamePasswordCredentials(username, password));

    Path caCertificatePath = Paths.get(path);
    SSLContext sslContext = null;
    try {
        CertificateFactory factory = CertificateFactory.getInstance("X.509");
        Certificate trustedCa;
        try (InputStream is = Files.newInputStream(caCertificatePath)) {
            trustedCa = factory.generateCertificate(is);
        }
        KeyStore trustStore = KeyStore.getInstance("pkcs12");
        trustStore.load(null, null);
        trustStore.setCertificateEntry("ca", trustedCa);
        SSLContextBuilder sslContextBuilder = SSLContexts.custom()
                .loadTrustMaterial(trustStore, null);
        sslContext = sslContextBuilder.build();
    } catch (CertificateException | IOException | KeyStoreException | NoSuchAlgorithmException | KeyManagementException e) {
        log.error("ES连接认证失败", e);
    }

    SSLContext finalSslContext = sslContext;
    RestClientBuilder builder = RestClient.builder(
            new HttpHost(host, port, scheme))
            .setHttpClientConfigCallback(httpClientBuilder -> httpClientBuilder
                    .setSSLContext(finalSslContext)
                    .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
                    .setDefaultCredentialsProvider(credentialsProvider));
    RestClient client = builder.build();
    return new RestClientTransport(client,new JacksonJsonpMapper());
}

查询
完全匹配-TermQuery
terms和term的查询机制是一样的,都不会将指定的查询关键字进行分词,直接去分词库中匹配,找到相应文档内容。

Query q = TermQuery.of(t -> t.field("filed").value(value))._toQuery();
1
模糊匹配-FuzzyQuery
Query q= FuzzyQuery.of(t -> t.field("filed").value(value))._toQuery();
1
in查询-TermsQuery
主键id可通过IdsQuery

 List<FieldValue> values = new ArrayList<>();
 for (Long id : list) {
     values.add(FieldValue.of(id));
 }
 Query idsQuery = TermsQuery.of(t -> t.field("filed").terms(new TermsQueryField.Builder()
         .value(values).build()
 ))._toQuery();

时间范围查询-Range
将日期转为时间戳查询 精确到毫秒

Query byTime = RangeQuery.of(r -> r
        .field("times")
        .gte(JsonData.of(startTime.getTime()))
        .lte(JsonData.of(endTime.getTime()))
)._toQuery();

排序-Sort
SortOptions.Builder sb = new SortOptions.Builder();
sb.field((f) -> {
            f.order(SortOrder.Desc);
            f.field("times");
            return f;
        }
);
SortOptions build = sb.build();
List<SortOptions> builders = Arrays.asList(build);

组合分页查询-Bool
must: 所有的条件,用must组合在一起,表示And的意思
must_not:将must_not中的条件,全部都不能匹配,表示Not的意思
should:所有的条件,用should组合在一起,表示Or的意思

 SearchRequest searchRequest = new SearchRequest.Builder()
                .index("index")
                .query(q -> q
                        .bool(
                                b -> {
                                    b.must(q);
                                    b.should(q1);
                                    return b;
                                }
                        )
                )
                .from(pageSize * pageNum)
                .size(pageSize)
                .sort(builders)
                .build();
SearchResponse<HashMap> search = client.search(searchRequest, HashMap.class);

扩展
文本匹配不到问题
因ES分词处理导致匹配不到
解决:

不需要做模糊查询的字段,使用keyword代替text,避免创建索引的时候对这些词进行分词。
 

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐