Elasticsearch集群_elasticsearch.cluster.name-程序员宅基地

技术标签: Java微服务  

今日授课目标

  • 能够完成索引库的操作:新增、查询、删除
  • 能够完成映射操作:配置映射,查看映射
  • 能够完成文档的操作:新增、修改、删除
  • 能完成请求体查询:基本查询、结果过滤、高亮查询,分页及排序

ES前置准备Lombok讲解

第一章 Elasticsearch集群

1.1 单点的问题

单台服务器,往往都有最大的负载能力,超过这个阈值,服务器性能就会大大降低甚至不可用。单点的elasticsearch也是一样,那单点的es服务器存在哪些可能出现的问题呢?

  • 单台机器存储容量有限
  • 单服务器容易出现单点故障,无法实现高可用
  • 单服务的并发处理能力有限

所以,为了应对这些问题,我们需要对elasticsearch搭建集群

集群中节点数量没有限制,大于等于2个节点就可以看做是集群了。一般出于高性能及高可用方面来考虑集群中节点数量都是3个以上。

1.2 相关概念

1.2.1 集群 cluster

一个集群就是由一个或多个节点组织在一起,它们共同持有整个的数据,并一起提供索引和搜索功能。一个集群由一个唯一的名字标识,这个名字默认就是“Elasticsearch”。这个名字是重要的,因为一个节点只能通过指定某个集群的名字,来加入这个集群

1.2.2 节点 node

一个节点是集群中的一个服务,作为集群的一部分,它存储数据,参与集群的索引和搜索功能。和集群类似,一个节点也是由一个名字来标识的。这个名字对于管理工作来说挺重要的,因为在这个管理过程中,你会去确定网络中的哪些服务对应于Elasticsearch集群中的哪些节点。

一个节点可以通过配置集群名称的方式来加入一个指定的集群。默认情况下,每个节点都会被安排加入到一个叫做“Elasticsearch”的集群中,这意味着,如果你在你的网络中启动了若干个节点,并假定它们能够相互发现彼此,它们将会自动地形成并加入到一个叫做“Elasticsearch”的集群中。在一个集群里,只要你想,可以拥有任意多个节点。

1.2.3 分片和复制 shards&replicas(副本)

为了解决索引占用空间过大(1TB以上)这个问题,Elasticsearch提供了将索引划分成多份的能力,这些份就叫做分片。当你创建一个索引的时候,你可以指定你想要的分片的数量。

为了提高分片高可用,Elasticsearch允许创建分片的一份或多份拷贝,这些拷贝叫做复制分片,或者直接叫复制。

默认情况下,Elasticsearch中的每个索引被分片5个主分片和1个复制,这意味着,如果你的集群中至少有两个节点,你的索引将会有5个主分片和另外5个复制分片(1个完全拷贝),这样的话每个索引总共就有10个分片。

ElasticSearch7.x之后,如果不指定索引分片,默认会创建1个分片

1.3 (伪)集群的搭建

1.3.1 准备三台Elasticsearch服务器

创建Elasticsearch-cluster文件夹,在内部复制三个Elasticsearch服务

1.3.2 修改每台服务器配置

修改Elasticsearch-cluster\node*\config\Elasticsearch.yml配置文件

node1节点:

#节点1的配置信息:
#集群名称,保证唯一
cluster.name: my-Elasticsearch
#节点名称,必须不一样
node.name: node-1
#必须为本机的ip地址
network.host: 127.0.0.1
#服务端口号,在同一机器下必须不一样
http.port: 9201
#集群间通信端口号,在同一机器下必须不一样
transport.tcp.port: 9301
#设置集群自动发现机器ip集合
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"]

node2节点:

#节点2的配置信息:
#集群名称,保证唯一
cluster.name: my-Elasticsearch
#节点名称,必须不一样
node.name: node-2
#必须为本机的ip地址
network.host: 127.0.0.1
#服务端口号,在同一机器下必须不一样
http.port: 9202
#集群间通信端口号,在同一机器下必须不一样
transport.tcp.port: 9302
#设置集群自动发现机器ip集合
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"]

node3节点:

#节点3的配置信息:
#集群名称,保证唯一
cluster.name: my-Elasticsearch
#节点名称,必须不一样
node.name: node-3
#必须为本机的ip地址
network.host: 127.0.0.1
#服务端口号,在同一机器下必须不一样
http.port: 9203
#集群间通信端口号,在同一机器下必须不一样
transport.tcp.port: 9303
#设置集群自动发现机器ip集合
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9301","127.0.0.1:9302","127.0.0.1:9303"]

1.3.3 启动各个节点服务器

双击cluster\node*\bin\Elasticsearch.bat

启动节点1:

启动节点2:

启动节点3:

1.3.4 集群测试

创建索引和配置映射

PUT /heima2
{
    "settings":{},
    "mappings":{
        "goods":{
            "properties":{
                "title":{
                    "type":"text",
                    "analyzer":"ik_max_word"
                },
                "subtitle":{
                    "type":"text",
                    "analyzer":"ik_max_word"
                },
                "images":{
                    "type":"keyword",
                    "index":"false"
                },
                "price":{
                    "type":"float"
                }
            }
        }
    }
}

添加文档

POST /heima2/goods
{
    "title":"小米手机",
    "images":"http://image.leyou.com/12479122.jpg",
    "price":2699.00
}

使用Elasticsearch-header查看集群情况

可以通过elasticsearch-head插件查看集群健康状态,有以下三个状态:

green

所有的主分片和副本分片都已分配。你的集群是 100% 可用的。

yellow

所有的主分片已经分片了,但至少还有一个副本是缺失的。不会有数据丢失,所以搜索结果依然是完整的。不过,你的高可用性在某种程度上被弱化。如果 更多的 分片消失,你就会丢数据了。把 yellow 想象成一个需要及时调查的警告。

red

至少一个主分片(以及它的全部副本)都在缺失中。这意味着你在缺少数据:搜索只能返回部分数据,而分配到这个分片上的写入请求会返回一个异常。

第二章 ElasticSearch高级Rest客户端

前面章节,我们学习了大量的命令操作Elasticsearch,本章我们将详细的介绍Spirng Boot整合Elasticsearch,通过Java代码操作ElasticSearch。

2.1 客户端开发环境搭建

Spring Boot集成Elasticsearch的时候,我们需要引入高阶客户端【elasticsearch-rest-high-level-client】【elasticsearch-rest-client】和【elasticsearch】来操作Elasticsearch,在引入起步依赖的时候,需要严格注意Elasticsearch和起步依赖的版本关系,否则在使用过程中会出很多问题

搭建步骤:

  1. 创建SpringBoot的项目,勾选starter配置
  2. 配置Maven依赖坐标
  3. 将ElasticSearch的客户端对象,注入Spring的容器
  4. 配置ElasticSearch,服务地址,端口号

搭建过程:

  1. 创建SpringBoot的项目,勾选starter配置

    • 选黑马spring Initializr
    • 配置项目信息
    • 勾选starter,开发者工具、Lombok、配置文件映射处理器
  2. 配置Maven依赖坐标


    org.elasticsearch.client
    elasticsearch-rest-high-level-client
    6.8.0



    org.elasticsearch.client
    elasticsearch-rest-client
    6.8.0



    org.elasticsearch
    elasticsearch
    6.8.0

  3. 将ElasticSearch的客户端对象,注入Spring的容器
    @Configuration
    @ConfigurationProperties(prefix = “elasticsearch”)
    @Component
    public class ElasticSearchConfig {

        private String host;
        private Integer port;
    
        //初始化RestHighLevelClient
        @Bean(destroyMethod = "close")
        public RestHighLevelClient client() {
            //RestClient客户端构建器对象
            RestClientBuilder restClientBuilder = RestClient.builder(new HttpHost(host, port, "http"));
            //操作es的高级rest客户端对象
            RestHighLevelClient restHighLevelClient = new RestHighLevelClient(restClientBuilder);
            return restHighLevelClient;
        }
    	//getter ,setter,toString..省略
    }
    
  4. 配置ElasticSearch,服务地址,端口号
    # es服务地址
    elasticsearch.host=127.0.0.1
    # es服务端口
    elasticsearch.port=9200
    # 配置日志级别,开启debug日志
    logging.level.com.itheima=debug

2.2 创建索引索引库

1、新增索引库

目标:使用ElasticSearch的高阶客户端,编写Java代码,创建索引库

分析:

Java high level客户端的操作,是模仿我们通过发送请求调用RESTful接口调用的方式,本质还是请求获取响应。

/**
 * 索引库操作:
 * 1.创建索引库
 * 2.查询索引库
 * 3.删除索引库
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo01IndexOperation {
    //注入ES客户端对象
    @Autowired
    private RestHighLevelClient client;
    /**
     * 目标:创建索引库
     * 1.创建请求对象
     *    设置索引库name
     * 2.客户端发送请求,获取响应对象
     * 3.打印响应对象中的返回结果
     * 4.关闭客户端,释放连接资源
     */
    @Test
    public void create() throws IOException {
        //1.创建请求对象,创建索引的请求
        CreateIndexRequest request = new CreateIndexRequest("heima3");
        //2.客户端发送请求,获取响应对象
        CreateIndexResponse response = client.indices().create(request, RequestOptions.DEFAULT);
        //3.打印响应对象中的返回结果
        //返回index信息
        System.out.println("index:"+response.index());
        //acknowledged代表创建成功
        System.out.println("acknowledged:"+response.isAcknowledged());
        //4.关闭客户端,释放连接资源
        client.close();
    }
}

执行结果:

发送请求中,传入请求对象的同时还设置了一个RequestOptions对象的静态成员变量DEFAULT。其含义是,配置当前请求选项为默认值。

其中RequestOptions对象的作用是用来配置请求,主要配置项目有请求头,缓冲区大小(默认100M),异常处理器(warningsHandler)。默认情况下,缓冲区大小100MB,请求头及异常处理器为空。

2、查看索引库

/**
 * 查询索引
 * 1.创建请求对象:查看索引库
 *    设置索引库name
 * 2.客户端发送请求,获取响应对象
 * 3.打印响应结果
 * 4.关闭客户端,释放连接资源
 */
@Test
public void getIndex() throws IOException {
    //1.创建请求对象:查看索引库
    GetIndexRequest request = new GetIndexRequest("heima4");
    //2.客户端发送请求,获取响应对象
    GetIndexResponse response = client.indices().get(request, RequestOptions.DEFAULT);
    //3.打印响应结果
    System.out.println("aliases: "+response.getAliases());
    System.out.println("settings: "+response.getSettings());
    System.out.println("mappings: "+response.getMappings());
    //4.关闭客户端,释放连接资源
    client.close();
}

执行结果:

3、删除索引库

/**
 * 删除索引
 * 1.创建请求对象:删除索引库
 *    设置索引库name
 * 2.客户端发送请求,获取响应对象
 * 3.打印响应结果
 * 4.关闭客户端,释放连接资源
 */
@Test
public void delete() throws IOException {
    //1.创建请求对象:删除索引库
    DeleteIndexRequest request = new DeleteIndexRequest("heima2");
    //2.客户端发送请求,获取响应对象
    AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
    //3.打印响应结果
    System.out.println("acknowledged::"+response.isAcknowledged());
    //4.关闭客户端,释放连接资源
    client.close();
}

执行结果:

2.3 配置映射

当配置Spring的ioc容器中的RestHighLevelClient对象的销毁执行方法之后,每次容器销毁对象时,必然会执行close方法,所以我们在使用完对象,可以不用每次手动关闭客户端。

1、配置映射

RestHighLevelClient配置映射,与kibana略有区别。在客户端中配置映射,不支持设置类型type。不设置type,并不代表没有,而是默认的type为_doc。

/**
 * 映射操作:
 * 1.配置映射,一共2种方式:
 *   第一种:使用XContentBuilder,构建请求体
 *   第二种:使用JSON字符串
 * 2.查看映射配置
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo02MappingOperation {
    //注入ES客户端对象
    @Autowired
    private RestHighLevelClient client;
    /**
     *目标:配置映射。第一种方式,使用XContentBuilder,构建请求体
     * 1.创建请求对象:配置映射
     *    设置索引库name
     *    设置配置映射请求体
     * 2.客户端发送请求,获取响应对象
     * 3.打印响应结果
     */
    @Test
    public void putMappingMethodOne() throws IOException {
        //1.创建请求对象:配置映射
        PutMappingRequest request = new PutMappingRequest("heima4");
        //构建请求体
        XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
        jsonBuilder.startObject()
                .startObject("properties")
                .startObject("title")
                .field("type","text").field("analyzer","ik_max_word")
                .endObject()
                .startObject("subtitle")
                .field("type","text").field("analyzer","ik_max_word")
                .endObject()
                .startObject("category")
                .field("type","keyword")
                .endObject()
                .startObject("brand")
                .field("type","keyword")
                .endObject()
                .startObject("images")
                .field("type","keyword").field("index",false)
                .endObject()
                .startObject("price")
                .field("type","float")
                .endObject()
                .endObject()
                .endObject();
        //设置请求体,source("请求体json构建器对象");
        request.source(jsonBuilder);
        //2.客户端发送请求,获取响应对象
        AcknowledgedResponse response = client.indices().putMapping(request, RequestOptions.DEFAULT);
        //3.打印响应结果
        System.out.println("acknowledged::"+response.isAcknowledged());
    }
}

执行结果:

第二种方式:

/**
 *目标:配置映射。第二种方式,使用JSON字符串
 * 1.创建请求对象:配置映射
 *    设置索引库name
 *    设置配置映射请求体
 * 2.客户端发送请求,获取响应对象
 * 3.打印响应结果
 */
@Test
public void putMappingMethodTwo() throws IOException {
    //1.创建请求对象:配置映射
    PutMappingRequest request = new PutMappingRequest("heima5");
    //设置请求体,source("请求体json字符串","请求体的数据类型");
    request.source("{\"properties\":{\"title\":{\"type\":\"text\",\"analyzer\":\"ik_max_word\"},\"subtitle\":{\"type\":\"text\",\"analyzer\":\"ik_max_word\"},\"category\":{\"type\":\"keyword\"},\"brand\":{\"type\":\"keyword\"},\"price\":{\"type\":\"float\"},\"images\":{\"type\":\"keyword\",\"index\":false}}}", XContentType.JSON);
    //2.客户端发送请求,获取响应对象
    AcknowledgedResponse response = client.indices().putMapping(request, RequestOptions.DEFAULT);
    //3.打印响应结果
    System.out.println("acknowledged::"+response.isAcknowledged());
}

执行结果:

2、查看映射

/**
 * 查看映射
 * 1.创建请求对象:查看映射
 *    设置索引库name
 * 2.客户端发送请求,获取响应对象
 * 3.打印响应结果
 */
@Test
public void getMapping() throws IOException {
    //1.创建请求对象:查看映射
    GetMappingsRequest request = new GetMappingsRequest();
    //设置索引库name
    request.indices("heima4");
    //2.客户端发送请求,获取响应对象
    GetMappingsResponse response = client.indices().getMapping(request, RequestOptions.DEFAULT);
    //3.打印响应结果
    System.out.println("mappings::"+response.mappings());
   System.out.println("Source::"+response.mappings().get("heima4").getSourceAsMap());
}

执行结果:

2.4 文档操作

1、创建文档

创建实体:

public class Goods {
    private Long id;//商品的唯一标识
    private String title;//标题
    private String subtitle;//子标题
    private String category;//分类
    private String brand;//品牌
    private Double price;//价格
    private String images;//图片地址
    //...getter , setter , toString
}

创建操作代码:

/**
 * 文档操作:
 * 1.新增文档
 * 2.根据id查询文档
 * 3.修改文档
 * 4.删除文档
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo03DocumentOperation {
    //注入ES客户端对象
    @Autowired
    private RestHighLevelClient client;
    /**
     * 目标:新增文档
     * 1.创建请求对象:新增文档
     *    设置索引库name
     *    设置类型type
     *    设置主键id,不设置随机生成
     *    设置请求体
     * 2.客户端发送请求,获取响应对象
     * 3.打印响应结果
     */
    @Test
    public void createDoc() throws IOException {
        //1.创建请求对象:新增文档
        IndexRequest request = new IndexRequest();
        //设置索引库名称
        request.index("heima4");
        //设置type类型
        request.type("_doc");
        //设置主键id
        request.id("1");
        //构造Goods对象
        Goods good = new Goods(1l,"小米手机","小米","手机","小米",19999.0,"http://image.leyou.com/12479122.jpg");
        //对象转json
        String goodJsonStr = new ObjectMapper().writeValueAsString(good);
        //设置请求体.source("json请求字符串","请求体的数据类型");
        request.source(goodJsonStr,XContentType.JSON);
        //2.客户端发送请求,获取响应对象
        IndexResponse response = client.index(request, RequestOptions.DEFAULT);
        //3.打印响应结果
        System.out.println("_index::"+response.getIndex());
        System.out.println("_type::"+response.getType());
        System.out.println("_id::"+response.getId());
        System.out.println("result::"+response.getResult());
    }
}

执行结果:

不设置主键ID:

2、修改文档

主键id相同,修改数据

/**
 * 修改文档
 * 1.创建请求对象:修改文档
 *    设置索引库name
 *    设置类型type
 *    设置主键id,必须设置
 *    设置请求体
 * 2.客户端发送请求,获取响应对象
 * 3.打印响应结果
 */
@Test
public void updateDoc() throws IOException {
    //1.创建请求对象:修改文档
    UpdateRequest request = new UpdateRequest();
    //设置索引库名称
    request.index("heima4");
    //设置type类型
    request.type("_doc");
    //设置主键id
    request.id("1");
    //构造Goods对象
    Goods good = new Goods(1l,"大米手机","炒米","手机","小米",999.0,"http://image.leyou.com/12479122.jpg");
    //对象转json
    String goodJsonStr = new ObjectMapper().writeValueAsString(good);
    //设置请求体.source("json请求字符串","请求体的数据类型");
    request.doc(goodJsonStr,XContentType.JSON);
    //2.客户端发送请求,获取响应对象
    UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
    //3.打印响应结果
    System.out.println("_index::"+response.getIndex());
    System.out.println("_type::"+response.getType());
    System.out.println("_id::"+response.getId());
    System.out.println("result::"+response.getResult());
}

执行结果:

3、根据id查询文档

/**
 * 根据id查询文档
 * 1.创建请求对象:根据id查询文档
 *    设置索引库name
 *    设置类型type
 *    设置主键id
 * 2.客户端发送请求,获取响应对象
 * 3.打印响应结果
 */
@Test
public void getDoc() throws IOException {
    //1.创建请求对象:根据id查询文档
    GetRequest request = new GetRequest();
    //设置索引库name
    request.index("heima4");
    //设置类型type
    request.type("_doc");
    //设置主键id
    request.id("1");
    //2.客户端发送请求,获取响应对象
    GetResponse response = client.get(request, RequestOptions.DEFAULT);
    //3.打印响应结果
    //3.打印响应结果
    System.out.println("_index::"+response.getIndex());
    System.out.println("_type::"+response.getType());
    System.out.println("_id::"+response.getId());
    System.out.println("_source::"+response.getSourceAsString());
}

执行结果:

4、删除文档

/**
 * 删除文档
 * 1.创建请求对象:删除文档
 *    设置索引库name
 *    设置类型type
 *    设置主键id
 * 2.客户端发送请求,获取响应对象
 * 3.打印响应结果
 */
@Test
public void deleteDoc() throws IOException {
    //1.创建请求对象:删除文档
    DeleteRequest request = new DeleteRequest();
    request.index("heima4");
    request.id("1");
    request.type("_doc");
    //2.客户端发送请求,获取响应对象
    DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
    //3.打印响应结果
    System.out.println("_index::"+response.getIndex());
    System.out.println("_type::"+response.getType());
    System.out.println("_id::"+response.getId());
    System.out.println("_result::"+response.getResult());
}

执行结果:

5、批量操作bulk

/**
 * 批量操作
 * 1.批量新增
 * 2.批量删除
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo04BulkOperation {
    //注入ES客户端对象
    @Autowired
    private RestHighLevelClient client;
    /**
     * 目标:批量新增
     * 1.创建请求对象:批量操作
     * 2.批量操作中设置多个新增对象IndexRequest
     * 3.客户端发送请求,获取响应对象
     * 4.打印响应结果
     */
    @Test
    public void createDoc() throws IOException {
        //1.创建请求对象:批量操作
        BulkRequest request = new BulkRequest();
        //2.批量操作中设置多个新增对象IndexRequest
        IndexRequest addRequestOne = new IndexRequest().id("1").type("_doc").index("heima3").source(XContentType.JSON,"id",1L,"title","大米手机","category","手机","brand","小米","price","2699.00","images","http://baidu.com");
        request.add(addRequestOne);
        IndexRequest addRequestTwo = new IndexRequest().id("2").type("_doc").index("heima3").source(XContentType.JSON,"id",2L,"title","大米手机","category","手机","brand","小米","price","2699.00","images","http://baidu.com");
        request.add(addRequestTwo);
        //3.客户端发送请求,获取响应对象
        BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
        //4.打印响应结果
        System.out.println("took::"+response.getTook());
        System.out.println("Items::"+response.getItems());
    }
    /**
     * 目标:批量删除
     * 1.创建请求对象:批量删除
     * 2.批量操作中设置多个删除对象DeleteRequest
     * 3.客户端发送请求,获取响应对象
     * 4.打印响应结果
     */
    @Test
    public void bulkDelete() throws IOException {
        //1.创建请求对象:批量删除
        BulkRequest request = new BulkRequest();
        //2.批量操作中设置多个删除对象DeleteRequest
        request.add(new DeleteRequest().id("1").type("_doc").index("heima3"));
        request.add(new DeleteRequest().id("2").type("_doc").index("heima3"));
        //3.客户端发送请求,获取响应对象
        BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
        //4.打印响应结果
        System.out.println("took::"+response.getTook());
        System.out.println("Items::"+response.getItems());
    }
}

执行结果:

第三章 高级Rest客户端-请求体查询

模拟数据

/**
 * 初始化查询数据
 */
@Test
public void initData() throws IOException {
    //批量新增操作
    BulkRequest request = new BulkRequest();
    request.add(new IndexRequest().type("_doc").index("heima3").source(XContentType.JSON,"title","大米手机","images","http://image.leyou.com/12479122.jpg","price",3288,"category","手机","brand","小米"));
    request.add(new IndexRequest().type("_doc").index("heima3").source(XContentType.JSON,"title","小米手机","images","http://image.leyou.com/12479122.jpg","price",2699,"category","手机","brand","小米"));
    request.add(new IndexRequest().type("_doc").index("heima3").source(XContentType.JSON,"title","小米电视4A","images","http://image.leyou.com/12479122.jpg","price",4288,"category","手机","brand","小米"));
    request.add(new IndexRequest().type("_doc").index("heima3").source(XContentType.JSON,"title","华为手机","images", "http://image.leyou.com/12479122.jpg","price", 5288,"subtitle", "小米","category","手机","brand","小米"));
    request.add(new IndexRequest().type("_doc").index("heima3").source(XContentType.JSON,"title","apple手机","images","http://image.leyou.com/12479122.jpg","price",5899.00,"category","手机","brand","小米"));
    BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
    System.out.println("took::"+response.getTook());
    System.out.println("Items::"+response.getItems());
}

3.1 基本查询

1、匹配查询(matchAll)

/**
 * 请求体查询-基本查询
 * 1.查询所有
 * 2.match查询,带分词器的查询
 * 3.multi_match查询,查询多个字段
 * 4.term查询,关键词精确匹配
 * 5.terms查询,多个关键词精确匹配
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo05RequestBodyQuery_Basic {
    //注入ES客户端对象
    @Autowired
    private RestHighLevelClient client;

    /**
     * 查询所有
     * 1.创建请求对象:查询所有
     *    设置索引库name
     *    设置类型type
     * 2.创建查询请求体构建器
     *    设置请求体
     * 3.客户端发送请求,获取响应对象
     * 4.打印响应结果
     */
    @Test
    public void matchAllQuery() throws IOException {
        //1.创建请求对象:查询所有
        SearchRequest request = new SearchRequest();
        request.types("_doc");
        request.indices("heima4");
        //2.创建查询请求体构建器
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //设置查询方式:matchAll
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        //设置请求体
        request.source(sourceBuilder);
        //3.客户端发送请求,获取响应对象
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.打印响应结果
        SearchHits hits = response.getHits();
        System.out.println("took::"+response.getTook());
        System.out.println("time_out::"+response.isTimedOut());
        System.out.println("total::"+hits.getTotalHits());
        System.out.println("max_score::"+hits.getMaxScore());
        System.out.println("hits::::>>");
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            System.out.println(sourceAsString);
        }
        System.out.println("<<::::");
    }  
}

执行结果:

2、匹配查询(match)

/**
 * 匹配查询,带分词器的查询
 * 分词后关键词之间的关系,or(默认),and
 * 1.创建请求对象:匹配查询
 *    设置索引库name
 *    设置类型type
 * 2.创建查询请求体构建器
 *    设置请求体
 * 3.客户端发送请求,获取响应对象
 * 4.打印响应结果
 */
@Test
public void matchQuery() throws IOException {
    //1.创建请求对象:匹配查询
    SearchRequest request = new SearchRequest();
    request.types("_doc");
    request.indices("heima4");
    //2.创建查询请求体构建器
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    //匹配查询,设置分词后关键词的查询关系,默认是or
    MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("title", "小米手机")
            .operator(Operator.AND);
    sourceBuilder.query(matchQueryBuilder);
    //设置请求体
    request.source(sourceBuilder);
    //3.客户端发送请求,获取响应对象
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    //4.打印响应结果
    printResult(response);
}
//打印结果信息
public void printResult(SearchResponse response) {
    SearchHits hits = response.getHits();
    System.out.println("took::"+response.getTook());
    System.out.println("time_out::"+response.isTimedOut());
    System.out.println("total::"+hits.getTotalHits());
    System.out.println("max_score::"+hits.getMaxScore());
    System.out.println("hits::::>>");
    for (SearchHit hit : hits) {
        String sourceAsString = hit.getSourceAsString();
        System.out.println(sourceAsString);
    }
    System.out.println("<<::::");
}

执行结果:

3、匹配查询(multi_match)

/**
 * 多字段匹配查询,查询title和subtitle
 * 1.创建请求对象:多字段匹配查询
 *    设置索引库name
 *    设置类型type
 * 2.创建查询请求体构建器
 *    设置请求体
 * 3.客户端发送请求,获取响应对象
 * 4.打印响应结果
 */
@Test
public void mulitMatchQuery() throws IOException {
    //1.创建请求对象
    SearchRequest request = new SearchRequest();
    request.types("_doc");
    request.indices("heima4");
    //2.创建查询请求体构建器
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    //设置查询方式:多字段匹配查询
    MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery("小米", "title", "subtitle");
    sourceBuilder.query(multiMatchQueryBuilder);
    //设置请求体
    request.source(sourceBuilder);
    //3.客户端发送请求,获取响应对象
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    //4.打印响应结果
    printResult(response);
}

执行结果:

4、关键词精确匹配查询(term)

/**
 * 关键词精确查询
 * 1.创建请求对象:关键词精确查询
 *    设置索引库name
 *    设置类型type
 * 2.创建查询请求体构建器
 *    设置请求体
 * 3.客户端发送请求,获取响应对象
 * 4.打印响应结果
 */
@Test
public void termQuery() throws IOException {
    //1.创建请求对象
    SearchRequest request = new SearchRequest();
    request.types("_doc");
    request.indices("heima4");
    //2.创建查询请求体构建器
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    //设置查询方式:关键词精确查询
    sourceBuilder.query(QueryBuilders.termQuery("title", "小米"));
    //设置请求体
    request.source(sourceBuilder);
    //3.客户端发送请求,获取响应对象
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    //4.打印响应结果
    printResult(response);
}

执行结果:

5、多关键词精确匹配查询(terms)

/**
 * 多关键词精确查询
 * 1.创建请求对象:多关键词精确查询
 *    设置索引库name
 *    设置类型type
 * 2.创建查询请求体构建器
 *    设置请求体
 * 3.客户端发送请求,获取响应对象
 * 4.打印响应结果
 */
@Test
public void termsQuery() throws IOException {
    //1.创建请求对象
    SearchRequest request = new SearchRequest();
    request.types("_doc");
    request.indices("heima4");
    //2.创建查询请求体构建器
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    //设置查询方式:多关键词精确查询
    sourceBuilder.query( QueryBuilders.termsQuery("title", "手机", "小米"));
    //设置请求体
    request.source(sourceBuilder);
    //3.客户端发送请求,获取响应对象
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    //4.打印响应结果
    printResult(response);
}

执行结果:

3.2 结果过滤,排序,分页

/**
 * 请求体查询-查询结果排除,分页,排序
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo06RequestBodyQuery_includes {
    //注入ES客户端对象
    @Autowired
    private RestHighLevelClient client;

    /**
     * 查询结果的排除
     * 1.创建请求对象:查询所有
     *    设置索引库name
     *    设置类型type
     * 2.创建查询请求体构建器
     *    设置请求体
     * 3.客户端发送请求,获取响应对象
     * 4.打印响应结果
     */
    @Test
    public void includesSources() throws IOException {
        //1.创建请求对象
        SearchRequest request = new SearchRequest();
        request.types("_doc");
        request.indices("heima4");
        //2.创建查询请求体构建器
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //设置查询方式
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        //设置过滤条件,包含和排除
        String[] includes = {"title","price","images"};
        String[] excludes = {"images"};
        sourceBuilder.fetchSource(includes,excludes);
        //设置排序
        FieldSortBuilder sortBuilder = SortBuilders.fieldSort("price");
        //设置排序降序
        sortBuilder.order(SortOrder.DESC);
        sourceBuilder.sort(sortBuilder);
        //设置分页
        sourceBuilder.from(0);//当前页起始索引
        sourceBuilder.size(5);//每页显示多少条
        //设置请求体
        request.source(sourceBuilder);
        //3.客户端发送请求,获取响应对象
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.打印响应结果
        printResult(response);
    }
    public void printResult(SearchResponse response) {
        SearchHits hits = response.getHits();
        System.out.println("took::"+response.getTook());
        System.out.println("time_out::"+response.isTimedOut());
        System.out.println("total::"+hits.getTotalHits());
        System.out.println("max_score::"+hits.getMaxScore());
        System.out.println("hits::::>>");
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            System.out.println(sourceAsString);
        }
        System.out.println("<<::::");
    }
}

执行结果:

3.3 高级查询

1、布尔查询(bool)

目标:查询title中必须包含小米,一定不含有电视,应该含有手机的所有商品

/**
 * 请求体查询-高级别查询
 * 1.布尔查询
 * 2.范围查询
 * 3.模糊查询
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo07QueryHighLevel {
    //注入ES客户端对象
    @Autowired
    private RestHighLevelClient client;
    /**
     * 目标:布尔查询,多条件组合查询
     * 1.创建请求对象:查询所有
     *    设置索引库name
     *    设置类型type
     * 2.创建查询请求体构建器
     *    设置请求体
     * 3.客户端发送请求,获取响应对象
     * 4.打印响应结果
     */
    @Test
    public void boolQuery() throws IOException {
        //1.创建请求对象
        SearchRequest request = new SearchRequest();
        request.types("_doc");
        request.indices("heima4");
        //2.创建查询请求体构建器
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //构建查询方式:布尔查询
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        //必须包含小米
        boolQueryBuilder.must(QueryBuilders.matchQuery("title","小米"));
        //必须不含电视
        boolQueryBuilder.mustNot(QueryBuilders.matchQuery("title","电视"));
        //应该含有手机
        boolQueryBuilder.should(QueryBuilders.matchQuery("title","手机"));
        //设置查询方式
        sourceBuilder.query(boolQueryBuilder);
        //设置请求体
        request.source(sourceBuilder);
        //3.客户端发送请求,获取响应对象
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.打印响应结果
        printResult(response);
    }
}

执行结果:

2、范围查询(range)

目标:查询价格大于2千,小于4千的所有商品

/**
 * 范围查询
 * 1.创建请求对象:范围查询
 *    设置索引库name
 *    设置类型type
 * 2.创建查询请求体构建器
 *    设置请求体
 * 3.客户端发送请求,获取响应对象
 * 4.打印响应结果
 */
@Test
public void rangeQuery() throws IOException {
    //1.创建请求对象
    SearchRequest request = new SearchRequest();
    request.types("_doc");
    request.indices("heima4");
    //2.创建查询请求体构建器
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    //构建查询方式:范围查询
    RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("price");
    //大于2千
    rangeQueryBuilder.gt(2000);
    //小于4千
    rangeQueryBuilder.lt(4000);
    //设置查询方式
    sourceBuilder.query(rangeQueryBuilder);
    //设置请求体
    request.source(sourceBuilder);
    //3.客户端发送请求,获取响应对象
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    //4.打印响应结果
    printResult(response);
}

执行结果:

3、模糊查询(fuzzy)

/**
 * 模糊查询,查询包含apple关键词的所有商品,完成模糊查询appla
 * 1.创建请求对象:模糊查询
 *    设置索引库name
 *    设置类型type
 * 2.创建查询请求体构建器
 *    设置请求体
 * 3.客户端发送请求,获取响应对象
 * 4.打印响应结果
 */
@Test
public void fuzzyQuery() throws IOException {
    //1.创建请求对象
    SearchRequest request = new SearchRequest().types("_doc").indices("heima4");
    //2.创建查询请求体构建器
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    //构建查询方式:模糊查询
    FuzzyQueryBuilder fuzzyQueryBuilder = QueryBuilders.fuzzyQuery("title", "appla");
    //设置偏差值
    fuzzyQueryBuilder.fuzziness(Fuzziness.ONE);
    //设置查询方式
    sourceBuilder.query(fuzzyQueryBuilder);
    //设置请求体
    request.source(sourceBuilder);
    //3.客户端发送请求,获取响应对象
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    //4.打印响应结果
    printResult(response);
}

执行结果:

3.4 高亮查询(Highlighter)

/**
 * 请求体查询-高亮查询
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class Demo08HighLighterQuery {
    //注入ES客户端对象
    @Autowired
    private RestHighLevelClient client;
    /**
     * 高亮查询,对查询关键词进行高亮
     * 1.创建请求对象:高亮查询
     *    设置索引库name
     *    设置类型type
     * 2.创建查询请求体构建器
     *    设置请求体
     * 3.客户端发送请求,获取响应对象
     * 4.打印响应结果
     */
    @Test
    public void highLighterQuery() throws IOException {
        //1.创建请求对象
        SearchRequest request = new SearchRequest().types("_doc").indices("heima4");
        //2.创建查询请求体构建器
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //构建查询方式:高亮查询
        TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("title", "小米");
        //设置查询方式
        sourceBuilder.query(termsQueryBuilder);
        //构建高亮字段
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font color='red'>");//设置标签前缀
        highlightBuilder.postTags("</font>");//设置标签后缀
        highlightBuilder.field("title");//设置高亮字段
        //设置高亮构建对象
        sourceBuilder.highlighter(highlightBuilder);
        //设置请求体
        request.source(sourceBuilder);
        //3.客户端发送请求,获取响应对象
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);

        //4.打印响应结果
        SearchHits hits = response.getHits();
        System.out.println("took::"+response.getTook());
        System.out.println("time_out::"+response.isTimedOut());
        System.out.println("total::"+hits.getTotalHits());
        System.out.println("max_score::"+hits.getMaxScore());
        System.out.println("hits::::>>");
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            System.out.println(sourceAsString);
            //打印高亮结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            System.out.println(highlightFields);
        }
        System.out.println("<<::::");
    }
}

执行结果:

第四章 Spring Data ElasticSearch 使用

4.1 Spring Data ElasticSearch简介

4.1.1 什么是Spring Data

Spring Data是一个用于简化持久层数据访问的开源框架。其主要目标是使得对数据的访问变得方便快捷。 Spring Data可以极大的简化数据操作的写法,可以在几乎不用写实现的情况下,实现对数据的访问和操作。包括CRUD外,还包括如分页、排序等一些常用的功能,几乎可以节省持久层代码80%以上的编码工作量。

Spring Data的官网:http://projects.spring.io/spring-data/

Spring Data常用的功能模块如下:

4.1.2 什么是Spring Data ElasticSearch

Spring Data ElasticSearch 基于 spring data API 简化 elasticSearch操作,将原始操作elasticSearch的客户端API 进行封装 。Spring Data为Elasticsearch项目提供集成搜索引擎。Spring Data Elasticsearch POJO的关键功能区域为中心的模型与Elastichsearch交互文档和轻松地编写一个存储库数据访问层。

官方网站:http://projects.spring.io/spring-data-elasticsearch/

用来操作ElasticSearch的框架,使得开发更加便捷

4.2 环境搭建

实现步骤:

  1. 创建SpringBoot的项目
  2. 勾选starter依赖坐标
  3. 编写持久层接口GoodDao,编写pojo实体类
  4. 配置文件,集群配置,ElasticSearch服务地址http://127.0.0.1:9300

实现过程:

  1. 创建SpringBoot的项目

  2. 勾选starter依赖坐标

  3. 编写持久层接口GoodDao,编写pojo实体类
    public interface GoodDao {
    }
    pojo实体类,商品good
    public class Good {
    private Long id;//商品的唯一标识
    private String title;//标题
    private String category;//分类
    private String brand;//品牌
    private Double price;//价格
    private String images;//图片地址
    //getter,setter,toString
    }

  4. 配置文件,集群配置,ElasticSearch服务地址http://127.0.0.1:9300
    # 配置集群名称
    spring.data.elasticsearch.cluster-name=elasticsearch
    # 配置es的服务地址
    spring.data.elasticsearch.cluster-nodes=127.0.0.1:9300

4.3 常用操作

1、创建索引库操作

几个用到的注解:

  • @Document:声明索引库配置
    • indexName:索引库名称
    • type:类型名称,默认是“docs”
    • shards:分片数量,默认5
    • replicas:副本数量,默认1
  • @Id:声明实体类的id
  • @Field:声明字段属性
    • type:字段的数据类型
    • analyzer:指定分词器类型
    • index:是否创建索引 默认为true
    • store:是否存储 默认为false

实体类配置:

/**
 * 商品实体类
 * @Document() 注解作用:定义一个索引库,一个类型
 * indexName属性:指定索引库的名称
 * type属性:指定类型名称
 * shards属性:指定分片数
 * replicas属性:指定复制副本数
 */
@Document(indexName = "heima4",type = "goods",shards = 5,replicas = 1)
public class Good {
    //必须有id,这里的id是全局唯一的标识,等同于es中的“_id”
    @Id
    private Long id;
    /**
     * type: 字段数据类型
     * analyzer: 分词器类型
     * index: 是否索引(默认值:true)
     * store: 是否存储(默认值:false)
     */
    @Field(type = FieldType.Text,analyzer = "ik_max_word")
    private String title;//标题
    @Field(type = FieldType.Keyword)
    private String category;//分类
    @Field(type = FieldType.Keyword)
    private String brand;//品牌
    @Field(type = FieldType.Double)
    private Double price;//价格
    @Field(type = FieldType.Keyword,index = false)
    private String images;//图片地址
	//getter ,setter ,toString
}

测试类:

/**
 * 目标:完成创建索引,配置映射
 * 1.注入ElasticSearchTemplate对象
 * 2.配置Good实体类
 * 3.调用创建索引的方法createIndex()
 *   调用配置映射的方法PutMapping()
 *   测试删除索引方法deleteIndex()
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringdataEsIndex {

    //注入ElasticSearchTemplate模板对象
    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;
    //创建索引,配置映射
    @Test
    public void createIndexAndPutMapping() {
        //创建索引
        boolean indexResult = elasticsearchTemplate.createIndex(Good.class);
        System.out.println("创建索引结果:"+indexResult);
        //创建配置映射
        elasticsearchTemplate.putMapping(Good.class);
        System.out.println("配置映射结果:"+indexResult);
    }
    //删除索引
    @Test
    public void deleteIndex(){
        elasticsearchTemplate.deleteIndex(Good.class);
    }
}

2、文档的常见增删改查

继承ElasticsearchRespository模板接口

/**
 *  继承持久层接口的ElasticSearch的模板接口
 */
public interface GoodDao extends ElasticsearchRepository<Good,Long> {
    
}

测试类代码:

/**
 * 目标:完成基本的增删改查操作
 * 新增、修改、删除、根据id查询、查询所有、分页查询
 * 步骤:
 * 1.dao层接口继承ElasticSearchRepository的模板接口
 * 2.编写业务层的所有方法
 * 3.测试所有方法
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringdataEsGoodCRUD {

    //注入Good业务层实现类
    @Autowired
    private GoodDao goodDao;
    /**
     * 新增
     */
    @Test
    public void save(){
        Good good = new Good();
        good.setId(1l);
        good.setTitle("小米手机");
        good.setCategory("手机");
        good.setBrand("小米");
        good.setPrice(19999.0);
        good.setImages("http://image.leyou.com/12479122.jpg");
        goodDao.save(good);
    }
    //修改
    @Test
    public void update(){
        Good good = new Good();
        good.setId(1l);
        good.setTitle("小米手机");
        good.setCategory("手机");
        good.setBrand("小米");
        good.setPrice(9999.0);
        good.setImages("http://image.leyou.com/12479122.jpg");
        goodDao.save(good);
    }
    //删除
    @Test
    public void delete(){
        Good good = new Good();
        good.setId(1l);
        goodDao.delete(good);
    }
    //根据id查询
    @Test
    public void findById(){
        Good good = goodDao.findById(2l).get();
        System.out.println(good);
    }
    //查询所有
    @Test
    public void findAll(){
        Iterable<Good> goods = goodDao.findAll();
        for (Good good : goods) {
            System.out.println(good);
        }
    }
    //批量新增
    @Test
    public void saveAll(){
        List<Good> goodList = new ArrayList<>();
        for (int i = 0; i < 100; i++) {
            Good good = new Good();
            good.setId((long) i);
            good.setTitle("["+i+"]小米手机");
            good.setCategory("手机");
            good.setBrand("小米");
            good.setPrice(19999.0+i);
            good.setImages("http://image.leyou.com/12479122.jpg");
            goodList.add(good);
        }
        goodDao.saveAll(goodList);
    }
    //分页查询
    @Test
    public void findByPageable(){
        //设置排序(排序方式,正序还是倒序,排序的id)
        Sort sort = new Sort(Sort.Direction.DESC,"id");
        int currentPage=2;//当前页
        int pageSize = 100;//每页显示多少条
        //设置查询分页
        PageRequest pageRequest = PageRequest.of(currentPage, pageSize,sort);
        //分页查询
        Page<Good> goodPage = goodDao.findAll(pageRequest);
        for (Good good : goodPage.getContent()) {
            System.out.println(good);
        }
    }
}

3、Search查询

ElasticSearch的search方法中QueryBuilders,就是第一章中的查询对象构建对象QueryBuilders。QueryBuilders具备的能力,search方法都具备。所以,在这里重复内容不赘述,仅举例term查询。

/**
 * 目标:搜索
 * term查询、match查询,match_all查询...
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringdataEsSearch {

    //注入Good业务层实现类
    @Autowired
    private GoodDao goodDao;

    /**
     * term查询
     * search(termQueryBuilder) 调用搜索方法,参数查询构建器对象
     */
    @Test
    public void termQuery(){
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", "小米");
        Iterable<Good> goods = goodDao.search(termQueryBuilder);
        for (Good g : goods) {
            System.out.println(g);
        }
    }
    /**
     * term查询加分页
     */
    @Test
    public void termQueryByPage(){
        int currentPage= 0 ;
        int pageSize = 5;
        //设置查询分页
        PageRequest pageRequest = PageRequest.of(currentPage, pageSize);
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", "小米");
        Iterable<Good> goods = goodDao.search(termQueryBuilder,pageRequest);
        for (Good g : goods) {
            System.out.println(g);
        }
    }
}

4、自定义方法名称查询

GoodsRepository提供了非常强大的自定义查询功能;只要遵循SpringData提供的语法,我们可以任意定义方法声明;

查询语法:findBy+字段名+Keyword+字段名+…

Keyword Sample Elasticsearch Query String
And findByNameAndPrice {“bool” : {“must” : [ {“field” : {“name” : “?”}}, {“field” : {“price” : “?”}} ]}}
Or findByNameOrPrice {“bool” : {“should” : [ {“field” : {“name” : “?”}}, {“field” : {“price” : “?”}} ]}}
Is findByName {“bool” : {“must” : {“field” : {“name” : “?”}}}}
Not findByNameNot {“bool” : {“must_not” : {“field” : {“name” : “?”}}}}
Between findByPriceBetween {“bool” : {“must” : {“range” : {“price” : {“from” : ?,“to” : ?,“include_lower” : true,“include_upper” : true}}}}}
Before findByPriceBefore {“bool” : {“must” : {“range” : {“price” : {“from” : null,“to” : ?,“include_lower” : true,“include_upper” : true}}}}}
After findByPriceAfter {“bool” : {“must” : {“range” : {“price” : {“from” : ?,“to” : null,“include_lower” : true,“include_upper” : true}}}}}
Like findByNameLike {“bool” : {“must” : {“field” : {“name” : {“query” : “?",“analyze_wildcard” : true}}}}}
StartingWith findByNameStartingWith {“bool” : {“must” : {“field” : {“name” : {“query” : "?
”,“analyze_wildcard” : true}}}}}
EndingWith findByNameEndingWith {“bool” : {“must” : {“field” : {“name” : {“query” : “*?”,“analyze_wildcard” : true}}}}}
In findByNameIn(Collectionnames) {“bool” : {“must” : {“bool” : {“should” : [ {“field” : {“name” : “?”}}, {“field” : {“name” : “?”}} ]}}}}
NotIn findByNameNotIn(Collectionnames) {“bool” : {“must_not” : {“bool” : {“should” : {“field” : {“name” : “?”}}}}}}
OrderBy findByNameOrderByNameDesc {“sort” : [{ “name” : {“order” : “desc”} }],“bool” : {“must” : {“field” : {“name” : “?”}}}

持久层接口:

/**
 *  ElasticsearchRepository 持久层操作ElasticSearch的模板接口
 */
public interface GoodDao extends ElasticsearchRepository<Good,Long> {
    /**
     * 根据title和价格查询,and的关系
     */
    List<Good> findAllByTitleAndPrice(String title,Double price);
    /**
     * 根据商品价格范围查询
     * 最低价格lowPrice
     * 最高价格highPrice
     */
    List<Good> findByPriceBetween(Double lowPrice,Double highPrice);
}

测试类:

/**
 * 自定义方法名称查询测试类
 */
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringdataEsCustomMethodQuery {

    //注入Good业务层实现类
    @Autowired
    private GoodDao goodDao;

    /**
     * 根据标题及价格查询
     * 要求价格等于20023且标题的内容包含小米关键词
     */
    @Test
    public void findAllByTitleAndPrice(){
        String title = "小米";
        Double price = 20023.0;
        List<Good> goods = goodDao.findAllByTitleAndPrice(title, price);
        for (Good g : goods) {
            System.out.println(g);
        }
    }
    /**
     * 根据价格范围查询
     * 要求商品价格再3000,到20000之间
     */
    @Test
    public void findPriceBetween(){
        double lowPrice = 3000.0;//最低价
        double highPrice = 20000.0;//最高价
        List<Good> goods = goodDao.findByPriceBetween(lowPrice, highPrice);
        for (Good g : goods) {
            Systemout.println(g);
        }
    }
}

总结

  1. 能够完成索引库的操作:新增、查询、删除
  2. 能够完成映射操作:配置映射,查看映射
  3. 能够完成文档的操作:新增、修改、删除
  4. 能完成请求体查询:基本查询、结果过滤、高亮查询,分页及排序
  5. 脑裂
  6. 聚合
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/aaa_56234/article/details/110632171

智能推荐

k-means聚类算法原理与参数调优详解_kmeans聚类算法-程序员宅基地

文章浏览阅读4.2w次,点赞26次,收藏223次。https://www.toutiao.com/a6690435044869145101/k-means算法原理K-means中心思想:事先确定常数K,常数K意味着最终的聚类类别数,首先随机选定初始点为质心,并通过计算每一个样本与质心之间的相似度(这里为欧式距离),将样本点归到最相似的类中,接着,重新计算每个类的质心(即为类中心),重复这样的过程,直到质心不再改变,最终就确定了每个样..._kmeans聚类算法

海康威视部分综合安防管理平台产品存在任意文件上传漏洞_海康威视综合安防管理平台任意文件上传漏洞-程序员宅基地

文章浏览阅读1.3k次。海康威视部分综合安防管理平台历史版本由于对上传文件接口校验不足,攻击者可以将恶意文件上传到平台,导致获取服务权限或服务异常。攻击者利用该漏洞上传Webshell,并随后执行任意命令,对主机上相关文件进行加密,加密后缀为locked1。海康威视iVMS集中监控应用管理平台,是以安全防范业务应用为导向,以视频图像应用为基础手段,综合视频监控、联网报警、智能分析、运维管理等多种安全防范应用系统,构建的多业务应用综合管理平台。(2)建立重要业务数据的定期备份机制,并做好权限隔离,防止勒索软件对备份数据进行加密;_海康威视综合安防管理平台任意文件上传漏洞

socket.io emit callback调用探秘-程序员宅基地

文章浏览阅读436次。socket.iohttps://socket.io/https://socket.io/docs/What Socket.IO isSocket.IO is a library that enables real-time, bidirectional and event-based communication between the browser and the s..._socket.io callback

Linux安装mpp数据库(Greenplum 集群部署)_用linux连接mpp数据库插入数据-程序员宅基地

文章浏览阅读1.3k次。下载greenplum-db-5.23.0-rhel7-x86_64.bin安装包个人百度网盘地址:链接:https://pan.baidu.com/s/1YCIo9vS0fSfi6pHwDLL5KQ 提取码:jmr6简单记录一下安装mpp(greenplum)的过程,以及遇到的问题。不喜勿喷简单来说GPDB是一个分布式数据库软件,其可以管理和处理分布在多个不同主机上的海量数据。对于GPDB来说,一个DB实例实际上是由多个独立的PostgreSQL实例组成的,它们分布在不同的物理主机上,协同工作,呈_用linux连接mpp数据库插入数据

docker api未授权导致rce 漏洞修复_docker未授权访问漏洞怎么修复-程序员宅基地

文章浏览阅读1.3k次。docker api未授权导致rce 漏洞修复_docker未授权访问漏洞怎么修复

设计模式-30-中介模式-行为型模式-程序员宅基地

文章浏览阅读673次,点赞30次,收藏10次。现在,我们来学习23种经典设计模式中的最后一个,中介模式。跟前面刚刚讲过的命令模式、解释器模式类似,中介模式也属于不怎么常用的模式,应用场景比较特殊、有限,但是,跟它俩不同的是,中介模式理解起来并不难,代码实现也非常简单,学习难度要小很多。如果你对中介模式有所了解,你可能会知道,中介模式跟之前讲过的观察者模式有点相似,所以,今天我们还会详细讨论下这两种模式的区别。

随便推点

vi一个简单操作_vi a.txt-程序员宅基地

文章浏览阅读399次。进入:打开VIM之后,按一下insert键或者i键就可以进入输入状态了 #vi a.txt退出:退出的时候先按Esc键,出来冒号(:)就可以敲命令, q! 回车 不保存 wq 保存 wq!强制保存并推出(适用与只读文件) x 保存_vi a.txt

vue3 antd pro 框架动态路由_vue3+ant design + ts+pro-程序员宅基地

文章浏览阅读629次。1. 在store/user.ts中,找到 GENERATE_ROUTES_DYNAMIC 方法中调用的方法:generatorDynamicRouter(),此方法在在router/router-guards/router-guards.ts中。2. router/router-guards/router-guards.ts中,通过方法getCurrentUserNav(),获取到个人信息中的菜单,将菜单列表传generator()方法中,此方法将菜单列表处理成路由所需格式的路由数组。_vue3+ant design + ts+pro

【华为云技术分享】敏捷开发落地不实际?原因可能在于你的 IDE 工具_华为云ide问题-程序员宅基地

文章浏览阅读3.5k次。对于企业来说,效率就是一切。开发效率的工程化建设已经开始被各大企业提到技术管理日程中。而且现阶段,无论是框架也好、模板也好,目的都是在为提升代码开发效率而努力。随着云计算的深入,端 + 云的开发模式以及完全云端化的开发模式都先后上线,这些无疑都是在对传统 IDE 开发模式的挑战。云端 IDE,会是未来的趋势吗?云时代下,万物上云正在影响企业研发效率工程化建设万物上云,可以说已经是不可逆..._华为云ide问题

数据库基础,进阶_数据库进阶知识包括哪些-程序员宅基地

文章浏览阅读223次。名称全称简称数据库存储数据的仓库,数据是有组织的进行存储数据库管理系统操纵和管理数据库的大型软件SQL操作关系型数据库的编程语言,定义了一套操作关系型数据库的统一标准主流的关系型数据库管理系统Oracle 收费昂贵MySQL 免费SQLserverPostgreSQL将一列数据作为一个整体,进行纵向计算概念:约束是作用于表中字段上的规则,用于限制存储在表中的数据。目的:保证数据库中数据的正确、有效性和完整性,统一性。约束描述关键字非空约束。_数据库进阶知识包括哪些

layui字体图标 loading图标静止不旋转_layui加载动画不会转圈-程序员宅基地

文章浏览阅读2.8k次,点赞3次,收藏2次。layui的字体图标库提供了丰富的字体图标,其中还有动态的loading图,但如果按照添加其他图标一样将class样式复制到按钮上,却发现loading图并不会旋转。_layui加载动画不会转圈

SAP 人力资源工资配置项2---工资类型配置_sap人员子类别如何对应工资等级-程序员宅基地

文章浏览阅读5.1k次。sap中使用工资等级管理工资_sap人员子类别如何对应工资等级

推荐文章

热门文章

相关标签