java初学ElasticSearch总结

64 阅读9分钟

简介

Elasticsearch是一个开源的分布式搜索和分析引擎,它构建在Apache Lucene搜索引擎库之上。它提供了一个强大而灵活的全文搜索和分析解决方案,具有高性能、可扩展性和容错性。

以下是Elasticsearch的一些关键特点:

  1. 分布式架构:Elasticsearch被设计为一个分布式系统,可以在多个节点上存储和处理数据。它使用了分片和副本机制,实现了数据的分布式存储和冗余备份,提供了高可用性和容错性。
  2. 实时搜索:Elasticsearch能够在毫秒级别内提供实时搜索和分析能力。当数据被索引后,它几乎可以立即被搜索到,使得对实时数据的查询和分析变得高效。
  3. 全文搜索:Elasticsearch支持全文搜索,可以对文本数据进行全文索引和搜索。它使用了先进的倒排索引技术,可以快速地找到与搜索查询匹配的文档。
  4. 强大的查询语言:Elasticsearch提供了丰富而灵活的查询语言,使用JSON格式构建查询请求。您可以执行各种类型的查询,包括匹配、范围、布尔逻辑、聚合等,以满足不同的搜索和分析需求。
  5. 分布式聚合:Elasticsearch支持在分布式环境下执行聚合操作,可以对大规模数据集进行统计、分组、汇总等操作。这使得从海量数据中提取有意义的信息变得更加便捷和高效。
  6. 数据可扩展性:Elasticsearch具有良好的可扩展性,可以根据需要水平扩展节点和集群,以处理大规模数据和高并发请求。它支持动态增加或删除节点,以适应不断变化的工作负载。
  7. 插件生态系统:Elasticsearch拥有丰富的插件生态系统,可以扩展其功能。这些插件可以用于数据预处理、分析和可视化等领域,帮助用户更好地利用和探索数据。

Elasticsearch被广泛应用于各种场景,包括实时日志分析、搜索引擎、企业搜索、商业智能、安全分析等。它提供了简单易用的API和工具,使得开发人员可以轻松地集成和利用其强大的搜索和分析功能。

官网地址:www.elastic.co/cn/elastics…

基本概念

1.索引(index)

索引库,类似于数据库的概念

2.类型(type)

类似于mysql中的table概念,一个索引库下有很多不同索引(类似库下的不同表)。

3.文档(Document)

以JSON格式定义的特定方式的字段集合。每个文档都属于一种类型,并且位于索引内。每个文档都与一个称为UID的唯一标识符相关联。

4.字段(Field)

说明:字段就是文档中的属性。

5.映射配置

字段的数据类型、属性、是否索引、是否存储等特性。 基本概念

1.索引(index)

索引库,类似于数据库的概念

2.类型(type)

类似于mysql中的table概念,一个索引库下有很多不同索引(类似库下的不同表)。

3.文档(Document)

以JSON格式定义的特定方式的字段集合。每个文档都属于一种类型,并且位于索引内。每个文档都与一个称为UID的唯一标识符相关联。

4.字段(Field)

说明:字段就是文档中的属性。

5.映射配置

字段的数据类型、属性、是否索引、是否存储等特性。

数据类型

1.简单数据类型

  • 字符串
  • 数值
  • 布尔
  • 二进制:binary
  • 范围类型
integer_range, float_range, long_range, double_range, date_range
  • 日期:date

2.复杂类型

• 数组 [ ] Nested: nested (for arrays of JSON objects 数组类型的JSON对象)

• 对象 { } Object: object(for single JSON objects 单个JSON对象)

原生语法

当前有一个user对象,包括姓名,年龄,爱好,手机号码,邮箱,下面使用Kibana对它进行增删改查

1.写数据

#使用put请求需要带上文档ID 
PUT /user_index/_doc/1 
{ "name": "John Doe", 
"age": 30, 
"hobbies": ["Reading", "Hiking", "Photography"], 
"phone": "1234567890",
"email": "johndoe@example.com"
} 
#使用post请求不带文档ID,由es自动分配 
POST /user_index/_doc
{ "name": "John Doe", 
"age": 30, 
"hobbies": ["Reading", "Hiking", "Photography"], 
"phone": "1234567890", 
"email": "johndoe@example.com" }

2.批量写数据

#批量插入使用Bulk API 
POST /user_index/_bulk 
{ "index": {} } { "name": "John shi", "age": 35, "hobbies": ["吃饭", "睡觉", "照相"], "phone": "1234567890", "email": "johndoe@example.com" } 
{ "index": {} } { "name": "Jane Smith", "age": 28, "hobbies": ["游泳", "跑步"], "phone": "9876543210", "email": "janesmith@example.com" } 
{ "index": {} } { "name": "Mike Johnson", "age": 35, "hobbies": ["旅游", "做饭"], "phone": "5555555555", "email": "mike@example.com" }

3.精确查询

#使用了"term"查询,同时指定了字段"name.keyword",这是一个未分词的关键字字段,它会精确匹配搜索词"John Doe"。
GET /user_index/_search 
 { "query": { 
      "term": { "name.keyword": "John Doe" 
      }
     }
  }

4.模糊查询

GET /user_index/_search
 { "query": { 
   "match": {
       "name": "John " 
      } 
    } 
 }

5.分页查询

#设置"from"参数为0,表示从第一条文档开始查询。通过设置"size"参数为10,表示每页查询10条文档 GET /user_index/_search
{ "query": { 
"match_all": {} 
}, 
"from": 1, 
"size": 2 
}

6.修改数据

POST /user_index/_update/1 
{ "doc":
 { "name": "John Doe",
"age": 33, 
"hobbies": ["Reading", "Hiking", "Photography", "Cooking"],
"phone": "9876543210", 
"email": "johndoe_updated@example.com" 
 }
}

7.删除数据

#根据id删除
DELETE /user_index/_doc/1

springboot集成es

1.引用依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

2.配置application.yml

spring:
  elasticsearch:
    rest:
      uris: http://127.0.0.1:9200

3.代码实现

3.1 创建实体类

package com.demo.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

/**
 * @description
 * @author: irving-shi
 * @date: 2023/8/4  10:28
 */
@Document(indexName = "es_user_index")
@Data
@AllArgsConstructor
public class EsUserInfo {

    @Id
    private Long id;
    // 姓名
    @Field(name = "name")
    private String name;

    // 年龄
    private Integer age;

    // 爱好
    private List<String> hobby;


    /**
     * 入职时间
     */
    @Field(name = "job_day",format= DateFormat.date_time)
    private Date jobDay;

    // 自我评价
    private String selfEvaluation;
    /**
     * 薪资
     */
    private BigDecimal salary;
}

@Document注解源码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.data.elasticsearch.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.elasticsearch.index.VersionType;
import org.springframework.data.annotation.Persistent;

@Persistent
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface Document {
    String indexName();    //索引库的名称

    /** @deprecated */
    @Deprecated
    String type() default "";  // 类型, 7.x之后已废弃

    boolean useServerConfiguration() default false; //默认不使用es服务器的配置,使用代码中的配置

    short shards() default 1;  // 分片数

    short replicas() default 1; // 每个分区默认的备份数

    String refreshInterval() default "1s"; // 刷新间隔

    String indexStoreType() default "fs";  //索引文件存储类型

    boolean createIndex() default true; // 是否创建索引

    VersionType versionType() default VersionType.EXTERNAL; //版本
}

@Field注解源码

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package org.springframework.data.elasticsearch.annotations;

import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.core.annotation.AliasFor;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD})
@Documented
@Inherited
public @interface Field {
    @AliasFor("name")
    String value() default ""; //属性别名

    @AliasFor("value")
    String name() default ""; //属性别名

    FieldType type() default FieldType.Auto; //属性类型,默认自动根据参数类型自动属性的类型

    boolean index() default true; /默认情况下分词

    DateFormat format() default DateFormat.none; //时间格式化

    String pattern() default "";

    boolean store() default false; //默认情况下不存储原文

    boolean fielddata() default false;

    String searchAnalyzer() default ""; //指定字段搜索时使用的分词器

    String analyzer() default ""; ;//指定字段建立索引时指定的分词器

    String normalizer() default "";//忽略某些字段

    String[] ignoreFields() default {};

    boolean includeInParent() default false;

    String[] copyTo() default {};

    int ignoreAbove() default -1;

    boolean coerce() default true;

    boolean docValues() default true;

    boolean ignoreMalformed() default false;

    IndexOptions indexOptions() default IndexOptions.none;

     、、、、
}

3.2创建xxRepository


package com.demo.repository;

import com.demo.entity.EsUserInfo;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.List;

/**
 * @description
 * @author: irving-shi
 * @date: 2023/8/4  10:37
 */
//泛型的参数分别是实体类型和主键类型
public interface EsUserInfoRepository extends ElasticsearchRepository<EsUserInfo,Long> {

   
}

3.3 创建service

package com.demo.service;

import com.demo.entity.EsUserInfo;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;

import java.util.Iterator;
import java.util.List;

/**
 * @description
 * @author: irving-shi
 * @date: 2023/8/4  10:39
 */
public interface EsUserInfoService {


    void deleteIndex(Long id);

    void save(EsUserInfo docBean);

    void saveAll(List<EsUserInfo> list);

    Iterator<EsUserInfo> findAll();

}

3。4 实现service

package com.demo.service.impl;

import com.demo.entity.EsUserInfo;
import com.demo.repository.EsUserInfoRepository;
import com.demo.service.EsUserInfoService;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.Iterator;
import java.util.List;

/**
 * @description
 * @author: irving-shi
 * @date: 2023/8/4 0004 10:40
 */
@Service
public class EsUserInfoServiceImpl implements EsUserInfoService {

    @Resource
    private EsUserInfoRepository esUserInfoRepository;

    @Override
    public void deleteIndex(Long id) {

        esUserInfoRepository.deleteById(id);
    }

    @Override
    public void save(EsUserInfo docBean) {
        esUserInfoRepository.save(docBean);
    }

    @Override
    public void saveAll(List<EsUserInfo> list) {
        esUserInfoRepository.saveAll(list);
    }

    @Override
    public Iterator<EsUserInfo> findAll() {
        return esUserInfoRepository.findAll().iterator();
    }
}

除了上述自带默认默认方法,还有类型jpa的实现,根据方法名,自动去实现

package com.demo.repository;

import com.demo.entity.EsUserInfo;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

import java.util.List;

/**
 * @description
 * @author: irving-shi
 * @date: 2023/8/4  10:37
 */
//泛型的参数分别是实体类型和主键类型
public interface EsUserInfoRepository extends ElasticsearchRepository<EsUserInfo,Long> {

    // 满足姓名和年龄条件
    List<EsUserInfo> findByNameAndAge(String name, Integer age);

    // 满足姓名或者年龄条件
    List<EsUserInfo> findByNameOrAge(String name,Integer age);

    // 不包含某某姓名条件
    Page<EsUserInfo> findByNameNot(String name, Pageable page);

    // 分页查询
    Page<EsUserInfo> findByName(String name, Pageable page);

    // LIKE 语句查询
    Page<EsUserInfo> findByNameLike(String name, Pageable page);
}

Elasticsearch 支持的关键字列表如下所示

KeywordSampleElasticsearch Query String
AndfindByNameAndPrice{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } }, { "query_string" : { "query" : "?", "fields" : [ "price" ] } } ] } }}
OrfindByNameOrPrice{ "query" : { "bool" : { "should" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } }, { "query_string" : { "query" : "?", "fields" : [ "price" ] } } ] } }}
IsfindByName{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } } ] } }}
NotfindByNameNot{ "query" : { "bool" : { "must_not" : [ { "query_string" : { "query" : "?", "fields" : [ "name" ] } } ] } }}
BetweenfindByPriceBetween{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }}
LessThanfindByPriceLessThan{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : false } } } ] } }}
LessThanEqualfindByPriceLessThanEqual{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }}
GreaterThanfindByPriceGreaterThan{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : false, "include_upper" : true } } } ] } }}
GreaterThanEqualfindByPriceGreaterThan{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : true, "include_upper" : true } } } ] } }}
BeforefindByPriceBefore{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : null, "to" : ?, "include_lower" : true, "include_upper" : true } } } ] } }}
AfterfindByPriceAfter{ "query" : { "bool" : { "must" : [ {"range" : {"price" : {"from" : ?, "to" : null, "include_lower" : true, "include_upper" : true } } } ] } }}
LikefindByNameLike{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}
StartingWithfindByNameStartingWith{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}
EndingWithfindByNameEndingWith{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "*?", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}
Contains/ContainingfindByNameContaining{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "*?*", "fields" : [ "name" ] }, "analyze_wildcard": true } ] } }}
In (when annotated as FieldType.Keyword)findByNameIn(Collection<String>names){ "query" : { "bool" : { "must" : [ {"bool" : {"must" : [ {"terms" : {"name" : ["?","?"]}} ] } } ] } }}
InfindByNameIn(Collection<String>names){ "query": {"bool": {"must": [{"query_string":{"query": ""?" "?"", "fields": ["name"]}}]}}}
NotIn (when annotated as FieldType.Keyword)findByNameNotIn(Collection<String>names){ "query" : { "bool" : { "must" : [ {"bool" : {"must_not" : [ {"terms" : {"name" : ["?","?"]}} ] } } ] } }}
NotInfindByNameNotIn(Collection<String>names){"query": {"bool": {"must": [{"query_string": {"query": "NOT("?" "?")", "fields": ["name"]}}]}}}
NearfindByStoreNearNot Supported Yet !
TruefindByAvailableTrue{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "true", "fields" : [ "available" ] } } ] } }}
FalsefindByAvailableFalse{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "false", "fields" : [ "available" ] } } ] } }}
OrderByfindByAvailableTrueOrderByNameDesc{ "query" : { "bool" : { "must" : [ { "query_string" : { "query" : "true", "fields" : [ "available" ] } } ] } }, "sort":[{"name":{"order":"desc"}}] }

单元测试

package com.demo.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.demo.ApplicationRunning;
import com.demo.entity.EsUserInfo;
import com.demo.repository.EsUserInfoRepository;
import com.demo.service.EsUserInfoService;
import org.junit.jupiter.api.Test;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;


import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;


/**
 * @description
 * @author: irving-shi
 * @date: 2023/8/4  10:48
 */
@SpringBootTest(classes = ApplicationRunning.class)
public class EsUserInfoServiceImplTest {

    @Autowired
    private EsUserInfoService esUserInfoService;

    @Resource
    private EsUserInfoRepository esUserInfoRepository;


    @Test
    public void deleteIndex() {
        esUserInfoRepository.deleteAll();

    }

    @Test
    public void save() throws Exception{
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
         esUserInfoService.save( new EsUserInfo(1000L, "张五", 20, Arrays.asList("骑马","编程","游泳"),  simpleDateFormat.parse("2019-09-10"), "精通java编程,擅长游泳",new BigDecimal(3000)));


    }

    @Test
    public void saveAll() throws Exception{

        List<EsUserInfo> list = new ArrayList<>();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        list.add(new EsUserInfo(1001L, "张三", 20, Arrays.asList("骑马","编程","游泳"),  simpleDateFormat.parse("2019-09-10"), "精通java编程,擅长游泳",new BigDecimal(3000)));
        list.add(new EsUserInfo(1002L, "张思", 19, Arrays.asList("吃饭","喝酒","游泳"),  simpleDateFormat.parse("2019-09-10"), "精通前端编码",new BigDecimal(3400)));
        list.add(new EsUserInfo(1003L, "张武", 20, Arrays.asList("睡觉","看书"), simpleDateFormat.parse("2019-09-10"), "精通mysql、redis等,并且热爱生活",new BigDecimal(3200)));
        list.add(new EsUserInfo(1004L, "李一", 21, Arrays.asList("骑马","编程","游泳"),  simpleDateFormat.parse("2019-09-10"), "天下第一人",new BigDecimal(4563)));
        list.add(new EsUserInfo(1005L, "李三", 23, Arrays.asList("做饭","编程","睡觉"),  simpleDateFormat.parse("2019-09-10"), "明日说唱明星",new BigDecimal(3456)));
        list.add(new EsUserInfo(1006L, "王二", 24, Arrays.asList("篮球","编程","游泳"), simpleDateFormat.parse("2019-09-10"), "篮球打的好,像那个男人",new BigDecimal(5432)));
        list.add(new EsUserInfo(1007L, "三六小", 24, Arrays.asList("篮球","睡觉","游泳"),  simpleDateFormat.parse("2019-09-10"), "无",new BigDecimal(3800)));
        list.add(new EsUserInfo(1008L, "吴小", 24, Arrays.asList("篮球","甜品"),  simpleDateFormat.parse("2019-09-10"), "喜欢睡觉,篮球,唱跳,rap",new BigDecimal(2999)));
        list.add(new EsUserInfo(1009L, "吴天里", 24, Arrays.asList("羽毛球","睡觉"),  simpleDateFormat.parse("2019-09-10"), "无",new BigDecimal(3200)));
        list.add(new EsUserInfo(1010L, "吴测试", 19, Arrays.asList("足球","跑步","游泳"), simpleDateFormat.parse("2019-09-10"), "无",new BigDecimal(3555)));
        esUserInfoService.saveAll(list);
    }

    @Test
    public void findAll() {


        System.out.println(JSON.toJSONString(esUserInfoService.findAll(), SerializerFeature.PrettyFormat));


    }

    @Test
    public void findByNameAndAge() {
        System.out.println(JSON.toJSONString(esUserInfoService.findByNameAndAge("张三",20), SerializerFeature.PrettyFormat));
        System.out.println(JSON.toJSONString(esUserInfoService.findByNameAndAge("张三",19), SerializerFeature.PrettyFormat));
    }

    @Test
    public void findByNameOrAge() {
        System.out.println(JSON.toJSONString(esUserInfoService.findByNameOrAge("张三",20), SerializerFeature.PrettyFormat));
        System.out.println(JSON.toJSONString(esUserInfoService.findByNameOrAge("张三",19), SerializerFeature.PrettyFormat));
    }

    @Test
    public void findByNameNot() {
        int pageNo = 0;
        int pageSize = 5;
        Pageable pageable = PageRequest.of(pageNo, pageSize);
        System.out.println(JSON.toJSONString(esUserInfoService.findByNameNot("张三",pageable), SerializerFeature.PrettyFormat));
    }

    @Test
    public void findByName() {
        int pageNo = 0;
        int pageSize = 5;
        Pageable pageable = PageRequest.of(pageNo, pageSize);
        System.out.println(JSON.toJSONString(esUserInfoService.findByName("张",pageable), SerializerFeature.PrettyFormat));
    }

    @Test
    public void findByNameLike() {
        int pageNo = 0;
        int pageSize = 5;
        Pageable pageable = PageRequest.of(pageNo, pageSize);
        System.out.println(JSON.toJSONString(esUserInfoService.findByNameLike("小",pageable), SerializerFeature.PrettyFormat));
    }
}

除上面方法之外,我们还可以用NativeSearchQueryBuilder进行高亮查询

package com.demo.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.demo.ApplicationRunning;
import com.demo.entity.EmployeeInfo;
import com.demo.entity.EsUserInfo;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedLongTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.SearchHitSupport;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.SearchPage;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @description
 * @author: irving-shi
 * @date: 2023/8/4  9:33
 */
@SpringBootTest(classes = ApplicationRunning.class)
public class EsUserHighLevelSearchTest {

    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    /**
     * 精确查询
     * 注:查询年龄20的记录
     */
    @Test
    public void findByNameTest() {

        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(QueryBuilders.termQuery("name.keyword", "张三"));
        println(nativeSearchQueryBuilder);
    }


    /**
     * AND 语句查询
     * 注:查询姓名为张三,年龄为19的记录
     */
    @Test
    public void findByNameAndAgeTest() {

        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        // 场景bool查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.must(QueryBuilders.matchPhraseQuery("name", "张三")).must(
                QueryBuilders.matchQuery("age", 20)
        );
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);

        println(nativeSearchQueryBuilder);
    }


    /**
     * OR 语句查询
     *
     * 注:查询姓名为张三,或者年龄为18的记录
     */

    @Test
    public void findByNameOrAgeTest() {
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        // 场景bool查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        boolQueryBuilder.should(QueryBuilders.matchPhraseQuery("name","张三")).should(QueryBuilders.matchQuery("age", 20));
        nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
        println(nativeSearchQueryBuilder);

    }



    /**
     * 聚合查询-groupBy
     */
    @Test
    public void groupByAge() {
        //1.构建查询对象
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.addAggregation(AggregationBuilders.terms("groupByAge").field("age").size(30));
        SearchHits<EmployeeInfo> search = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), EmployeeInfo.class);
        Aggregations aggregations = search.getAggregations();
        ParsedLongTerms parsedLongTerms = aggregations.get("groupByAge");
        List<String> ageList =  parsedLongTerms.getBuckets().stream().map(Terms.Bucket::getKeyAsString).collect(Collectors.toList());
        System.out.println(ageList);
    }



    /**
     * 分页查询
     * 带参数
     */
    @Test
    public void listPageMatch() {
        int pageNo = 1;
        int pageSize = 5;
        NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
        nativeSearchQueryBuilder.withQuery(QueryBuilders.matchQuery("name","小"));
        //注:Pageable类中 pageNum需要减1,如果是第一页 数值为0
        Pageable pageable = PageRequest.of(pageNo-1,pageSize);

        SearchHits<EmployeeInfo> searchHitsResult = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), EmployeeInfo.class);

        //7.获取分页数据
        SearchPage<EmployeeInfo> searchPageResult = SearchHitSupport.searchPageFor(searchHitsResult,pageable);
        System.out.println("分页查询");
        System.out.println(String.format("totalPages:%d, pageNo:%d, size:%d", searchPageResult.getTotalPages(), pageNo, pageSize));
        System.out.println(JSON.toJSONString(searchPageResult.getSearchHits(), SerializerFeature.PrettyFormat));
    }


        /**
         * 打印高亮查询对象,对象列表打印
         */
    private void println(NativeSearchQueryBuilder nativeSearchQueryBuilder) {

        SearchHits<EsUserInfo> search = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), EsUserInfo.class);
        List<EsUserInfo> employeeInfoList = new ArrayList<>();

        search.forEach(
                s -> {
                    EsUserInfo esUserInfo = s.getContent();
                    employeeInfoList.add(esUserInfo);
                }
        );
        System.out.println(JSON.toJSONString(search.getSearchHits(), SerializerFeature.PrettyFormat));
        System.out.println(employeeInfoList);

    }
}

另外对于复杂的聚合查询后续将进行补充学习