SpringCloud微服务(三)RabbitMQ、SpringAMQP、elasticsearch、DSL、MQ、ES详细介绍

目录

一、初始MQ

同步调用

异步调用

什么是MQ

执行下面的命令来运行MQ容器:

如果冲突了,可以先查询

RabbitMQ概述 

常见消息模型

HelloWorld案例

二、SpringAMQP

引入依赖

Work Queue 

消费预取限制

​编辑 发布、订阅

发布订阅Fanout Exchange

发布DirectExchange

发布订阅TopicExchange 

消息转化器

MQ代码

三、什么是elasticsearch

 正向索引

倒排索引

文档

索引

概念对比

架构 

 ​编辑

部署单点es

1.2.加载镜像

1.3.运行

命令解释:

2.1.部署

 分词器

2.2.DevTools

kibana中提供了一个DevTools界面:

3.安装IK分词器

3.1.在线安装ik插件(较慢)

3.2.离线安装ik插件(推荐)

1)查看数据卷目录

2)解压缩分词器安装包

3)上传到es容器的插件数据卷中

4)重启容器

5)测试:

3.3 扩展词词典

四、索引库操作 

创建索引库

查看、删除索引库​编辑

修改索引库

 新增文档​编辑

 查看、删除文档​编辑

修改文档

RestClient操作索引库

索引库代码

RestClient操作文档

操作文档代码

DSL 查询文档

 DSL  Query的分类​编辑

DSL Query基本语法

 全文检索查询​编辑

 精确查询​编辑

 地理查询​编辑

相关性算分

 Function Score Query​编辑

复合查询 Boolean Query

 搜索结果处理​编辑

分页

深度分页问题

​编辑高亮 

RestClient查询文档

全文检索查询

精确查询 ​编辑

符合查询

排序和分页

 高亮​编辑


初始MQ

同步调用

异步调用

什么是MQ

执行下面的命令来运行MQ容器:

docker run \
 -e RABBITMQ_DEFAULT_USER=itcast \
 -e RABBITMQ_DEFAULT_PASS=123321 \
 --name mq \
 --hostname mq1 \
 -p 15672:15672 \
 -p 5672:5672 \
 -d \
 rabbitmq:3-management

如果冲突了,可以先查询

RabbitMQ概述 

常见消息模型

HelloWorld案例

 

SpringAMQP

 

引入依赖

 

Work Queue 

 

 

消费预取限制

 发布、订阅

发布订阅Fanout Exchange

发布DirectExchange

发布订阅TopicExchange 

 

 

消息转化器

MQ代码


@Component
public class SpringRabbitListener {

//    @RabbitListener(queues = "simple.queue")
//    public void listenSimpleQueue(String msg){
//        System.out.println("消费者接收到simple.queue的消息:["+msg+"]");
//
//    }

    @RabbitListener(queues = "simple.queue")
    public void listenWorkQueue1(String msg) throws InterruptedException {
        System.out.println("消费者1接收到simple.queue的消息:["+msg+"]"+ LocalTime.now());
        Thread.sleep(20);
    }

    @RabbitListener(queues = "simple.queue")
    public void listenWorkQueue2(String msg) throws InterruptedException {
        System.err.println("消费者2接收到simple.queue的消息:["+msg+"]"+LocalTime.now());
        Thread.sleep(200);
    }

        @RabbitListener(queues = "fanout.queue1")
    public void listenFanoutQueue1(String msg){
        System.out.println("消费者接收到fanout.queue1的消息:["+msg+"]");

    }

    @RabbitListener(queues = "fanout.queue2")
    public void listenFanoutQueue2(String msg){
        System.out.println("消费者接收到fanout.queue2的消息:["+msg+"]");

    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "direct.queue1"),
            exchange = @Exchange(name = "itcast.direct",type = ExchangeTypes.DIRECT),
            key = {"red","blue"}
    ))
    public void listenDirectQueue1(String msg){
        System.out.println("消费者接收到direct.queue1的消息:["+msg+"]");
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "direct.queue2"),
            exchange = @Exchange(name = "itcast.direct",type = ExchangeTypes.DIRECT),
            key = {"red","yellow"}
    ))
    public void listenDirectQueue2(String msg){
        System.out.println("消费者接收到direct.queue2的消息:["+msg+"]");
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "topic.queue1"),
            exchange = @Exchange(name = "itcast.topic",type = ExchangeTypes.TOPIC),
            key = "china.#"
    ))
    public void listenTopicQueue1(String msg){
        System.out.println("消费者接收到topic.queue1的消息:["+msg+"]");
    }

    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(name = "topic.queue2"),
            exchange = @Exchange(name = "itcast.topic",type = ExchangeTypes.TOPIC),
            key = "#.news"
    ))
    public void listenTopicQueue2(String msg){
        System.out.println("消费者接收到topic.queue2的消息:["+msg+"]");
    }

    @RabbitListener(queues = "object.queue")
    public void listObjectQueue(Map<String,Object> msg){

        System.out.println("接收object.queue的消息:"+msg);
    }
}

@Configuration
public class FanoutConfig {
    //声明FanoutExchange 交换机
    //itcast.fanout
    @Bean
    public FanoutExchange fanoutExchange(){
        return new FanoutExchange("itcast.fanout");
    }
    //声明一个队列fanout.queue1
    @Bean
    public Queue fanoutQueue1(){
        return new Queue("fanout.queue1");
    }
    //绑定队列1和交换机
    @Bean
     public Binding fanoutBinding1(Queue fanoutQueue1,FanoutExchange fanoutExchange){
        return BindingBuilder
                .bind(fanoutQueue1)
                .to(fanoutExchange);

     }
    //fanout.queue2
    //声明一个队列fanout.queue1
    @Bean
    public Queue fanoutQueue2(){
        return new Queue("fanout.queue2");
    }
    //绑定队列1和交换机
    @Bean
    public Binding fanoutBinding2(Queue fanoutQueue2,FanoutExchange fanoutExchange){
        return BindingBuilder
                .bind(fanoutQueue2)
                .to(fanoutExchange);

    }

    @Bean
    public Queue objectQueue(){
        return new Queue("object.queue");
    }

}


@SpringBootApplication
public class ConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(ConsumerApplication.class, args);
    }
    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }
}

public class PublisherTest {
    @Test
    public void testSendMessage() throws IOException, TimeoutException {
        // 1.建立连接
        ConnectionFactory factory = new ConnectionFactory();
        // 1.1.设置连接参数,分别是:主机名、端口号、vhost、用户名、密码
        factory.setHost("虚拟机地址");
        factory.setPort(5672);
        factory.setVirtualHost("/");
        factory.setUsername("itcast");
        factory.setPassword("123321");
        // 1.2.建立连接
        Connection connection = factory.newConnection();

        // 2.创建通道Channel
        Channel channel = connection.createChannel();

        // 3.创建队列
        String queueName = "simple.queue";
        channel.queueDeclare(queueName, false, false, false, null);

        // 4.发送消息
        String message = "hello, rabbitmq!";
        channel.basicPublish("", queueName, null, message.getBytes());
        System.out.println("发送消息成功:【" + message + "】");

        // 5.关闭通道和连接
        channel.close();
        connection.close();

    }
}

@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringAmqpTest {
    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Test
    public void testSendMessage2SimpleWueue(){
        String queueName = "simple.queue";
        String message = "hello,spring amqp!!!";
        rabbitTemplate.convertAndSend(queueName,message);
    }

    @Test
    public void testSendMessage2WorkQueue() throws InterruptedException {
        String queueName = "simple.queue";
        String message = "hello,message__";
        for ( int i = 1; i <= 50; i++ ) {
            rabbitTemplate.convertAndSend(queueName,message+i);
            Thread.sleep(20);
        }
    }

    @Test
    public void testSendFanoutExchange(){
        //交换机名称
        String exchangeName = "itcast.fanout";
        //消息
        String message = "hello,every one !";
        //发送消息
        rabbitTemplate.convertAndSend(exchangeName,"",message);
    }

    @Test
    public void testSendDirectExchange(){
        //交换机名称
        String exchangeName = "itcast.direct";
        //消息
        String message = "hello,blue !";
        //发送消息
        rabbitTemplate.convertAndSend(exchangeName,"red",message);
    }

    @Test
    public void testSendTopicExchange(){
        //交换机名称
        String exchangeName = "itcast.topic";
        //消息
        String message = "中国NO.1";
        //发送消息
        rabbitTemplate.convertAndSend(exchangeName,"chi.weather",message);
    }

    @Test
    public void testSendObjectExchange(){
        HashMap<String, Object> msg = new HashMap<>();
        msg.put("name","留言2");
        msg.put("age",21);
        //发送消息
        rabbitTemplate.convertAndSend("object.queue",msg);
    }





}

什么是elasticsearch

 

 

 正向索引

倒排索引

 

文档

索引

概念对比

架构 

 

 

部署单点es

因为我们还需要部署kibana容器,因此需要让es和kibana容器互联。这里先创建一个网络:

docker network create es-net

1.2.加载镜像

这里我们采用elasticsearch的7.12.1版本的镜像,这个镜像体积非常大,接近1G。不建议大家自己pull。

课前资料提供了镜像的tar包:

 大家将其上传到虚拟机中,然后运行命令加载即可:

# 导入数据
docker load -i es.tar

同理还有kibana的tar包也需要这样做。

1.3.运行

运行docker命令,部署单点es:

docker run -d \
	--name es \
    -e "ES_JAVA_OPTS=-Xms512m -Xmx512m" \
    -e "discovery.type=single-node" \
    -v es-data:/usr/share/elasticsearch/data \
    -v es-plugins:/usr/share/elasticsearch/plugins \
    --privileged \
    --network es-net \
    -p 9200:9200 \
    -p 9300:9300 \
elasticsearch:7.12.1

命令解释:

  • -e "cluster.name=es-docker-cluster":设置集群名称

  • -e "http.host=0.0.0.0":监听的地址,可以外网访问

  • -e "ES_JAVA_OPTS=-Xms512m -Xmx512m":内存大小

  • -e "discovery.type=single-node":非集群模式

  • -v es-data:/usr/share/elasticsearch/data:挂载逻辑卷,绑定es的数据目录

  • -v es-logs:/usr/share/elasticsearch/logs:挂载逻辑卷,绑定es的日志目录

  • -v es-plugins:/usr/share/elasticsearch/plugins:挂载逻辑卷,绑定es的插件目录

  • --privileged:授予逻辑卷访问权

  • --network es-net :加入一个名为es-net的网络中

  • -p 9200:9200:端口映射配置

在浏览器中输入:http://192.168.150.101:9200 即可看到elasticsearch的响应结果:

 kibana可以给我们提供一个elasticsearch的可视化界面,便于我们学习。

2.1.部署

运行docker命令,部署kibana(版本一定要一样)

docker run -d \
--name kibana \
-e ELASTICSEARCH_HOSTS=http://es:9200 \
--network=es-net \
-p 5601:5601  \
kibana:7.12.1
  • --network es-net :加入一个名为es-net的网络中,与elasticsearch在同一个网络中

  • -e ELASTICSEARCH_HOSTS=http://es:9200":设置elasticsearch的地址,因为kibana已经与elasticsearch在一个网络,因此可以用容器名直接访问elasticsearch

  • -p 5601:5601:端口映射配置

kibana启动一般比较慢,需要多等待一会,可以通过命令:

docker logs -f kibana

查看运行日志,当查看到下面的日志,说明成功:

 分词器

2.2.DevTools

kibana中提供了一个DevTools界面:

 这个界面中可以编写DSL来操作elasticsearch。并且对DSL语句有自动补全功能。

3.安装IK分词器

3.1.在线安装ik插件(较慢)

# 进入容器内部
docker exec -it elasticsearch /bin/bash

# 在线下载并安装
./bin/elasticsearch-plugin  install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.12.1/elasticsearch-analysis-ik-7.12.1.zip

#退出
exit
#重启容器
docker restart elasticsearch

3.2.离线安装ik插件(推荐)

1)查看数据卷目录

安装插件需要知道elasticsearch的plugins目录位置,而我们用了数据卷挂载,因此需要查看elasticsearch的数据卷目录,通过下面命令查看:

docker volume inspect es-plugins

显示结果:

[
    {
        "CreatedAt": "2022-05-06T10:06:34+08:00",
        "Driver": "local",
        "Labels": null,
        "Mountpoint": "/var/lib/docker/volumes/es-plugins/_data",
        "Name": "es-plugins",
        "Options": null,
        "Scope": "local"
    }
]

说明plugins目录被挂载到了:/var/lib/docker/volumes/es-plugins/_data这个目录中。

2)解压缩分词器安装包

下面我们需要把课前资料中的ik分词器解压缩,重命名为ik

3)上传到es容器的插件数据卷中

4)重启容器

# 4、重启容器
docker restart es
# 查看es日志
docker logs -f es

5)测试:

IK分词器包含两种模式:

  • ik_smart:最少切分

  • ik_max_word:最细切分

GET /_analyze
{
  "analyzer": "ik_max_word",
  "text": "我爱学习java太棒了"
}

结果:

{
  "tokens" : [
    {
      "token" : "我",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "CN_CHAR",
      "position" : 0
    },
    {
      "token" : "爱学习",
      "start_offset" : 1,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 1
    },
    {
      "token" : "学习",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "java",
      "start_offset" : 4,
      "end_offset" : 8,
      "type" : "ENGLISH",
      "position" : 3
    },
    {
      "token" : "太棒了",
      "start_offset" : 8,
      "end_offset" : 11,
      "type" : "CN_WORD",
      "position" : 4
    },
    {
      "token" : "太棒",
      "start_offset" : 8,
      "end_offset" : 10,
      "type" : "CN_WORD",
      "position" : 5
    },
    {
      "token" : "了",
      "start_offset" : 10,
      "end_offset" : 11,
      "type" : "CN_CHAR",
      "position" : 6
    }
  ]
}

3.3 扩展词词典

随着互联网的发展,“造词运动”也越发的频繁。出现了很多新的词语,在原有的词汇列表中并不存在。比如:“奥力给”,“传智播客” 等。

所以我们的词汇也需要不断的更新,IK分词器提供了扩展词汇的功能。

1)打开IK分词器config目录:

 2)在IKAnalyzer.cfg.xml配置文件内容添加:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
        <comment>IK Analyzer 扩展配置</comment>
        <!--用户可以在这里配置自己的扩展字典 *** 添加扩展词典-->
        <entry key="ext_dict">ext.dic</entry>
</properties>

索引库操作 

创建索引库

#创建索引库
PUT /heihei
{
  "mappings": {
    "properties": {
      "info": {
        "type": "text",
        "analyzer": "ik_smart"
      },
      "email": {
        "type": "keyword",
        "index": false
      },
      "name": {
        "type": "object",
        "properties": {
          "firstName": {
            "type": "keyword"
          },
           "lastName": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

查看、删除索引库

 

修改索引库

 

 

 

 新增文档

 查看、删除文档

修改文档

 

RestClient操作索引库

 

 

#酒店的mapping
PUT /hotel
{
  "mappings": {
    "properties": {
      "id":{
        "type": "keyword"
      },
      "name":{
        "type": "text",
        "analyzer": "ik_max_word"
      },
      "adress":{
        "type": "keyword",
        "index": false
      },
      "price":{
        "type": "integer"
      },
      "score":{
        "type": "integer"
      },
      "brand":{
        "type": "keyword"
      },
      "city":{
        "type": "keyword"
      },
      "starName":{
        "type": "keyword"
      },
      "business":{
        "type": "keyword"
      },
      "location":{
        "type": "geo_point"
      },
      "pic":{
        "type": "keyword",
        "index": false
      }
    }
  }
}

索引库代码


public class HotelIndexTest {
    private RestHighLevelClient client;

    @Test
    void testInit(){
        System.out.println(client);
    }
    @Test
    void createHotelIndex() throws IOException {
        //1.创建Request对象
        CreateIndexRequest request = new CreateIndexRequest("hotel");
        //2.准备请求的参数,DSL语句
        request.source(MAPPTING_TEMPLATE, XContentType.JSON);
        //3.发送请求
        client.indices().create(request, RequestOptions.DEFAULT);
    }


    @Test
    void deleteHotelIndex() throws IOException {
        //1.创建Request对象
        DeleteIndexRequest request = new DeleteIndexRequest("hotel");

        //3.发送请求
        client.indices().delete(request, RequestOptions.DEFAULT);
    }

    @Test
    void testExistHotelIndex() throws IOException {
        //1.创建Request对象
        GetIndexRequest request = new GetIndexRequest("hotel");

        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        //3.发送请求
        System.err.println(exists ? "索引库已经存在" : "索引库不存在!");
    }

    @BeforeEach
    void setUp(){
        this.client = new RestHighLevelClient(
                RestClient.builder(HttpHost.create("http://虚拟机地址:es端口号")
                ));
    }

    @AfterEach
    void tearDown()throws IOException{
        this.client.close();
    }
}

RestClient操作文档

 

 

 

操作文档代码


@SpringBootTest
public class HotelDocumentTest {

    @Autowired
    private IHotelService hotelService;

    private RestHighLevelClient client;

    @Test
    void testAddDcoument() throws IOException {
        //根据id查询酒店数据
        Hotel hotel = hotelService.getById(36934L);
        //转化为文档类型
        HotelDoc hotelDoc = new HotelDoc(hotel);

        //1.准备Request对象
        IndexRequest request = new IndexRequest("hotel").id(hotel.getId().toString());
        //2.准备Json文件
        request.source(JSON.toJSONString(hotelDoc),XContentType.JSON);
        client.index(request,RequestOptions.DEFAULT);
        //3.发送请求
    }

    @Test
    void testGetDocumentById() throws IOException {
        //1.准备Request
        GetRequest request = new GetRequest("hotel", "36934");
        //2.发送请求,得到响应
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        //3.解析响应结果
        String json = response.getSourceAsString();

        HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
        System.out.println(hotelDoc);

    }

    @Test
    void testRulkRequest() throws IOException {
        //批量查询酒店数据
        List<Hotel> hotels = hotelService.list();


        //1.创建Request
        BulkRequest request = new BulkRequest();
        //2.准备参数,添加多个新增的Request
        for ( Hotel hotel : hotels ) {
            //转换为文档类型HotelDoc
            HotelDoc hotelDoc = new HotelDoc(hotel);
            //2.准备参数,添加多个新增的Request
            request.add(new IndexRequest("hotel")
                    .id(hotel.getId().toString())
                    .source(JSON.toJSONString(hotelDoc),XContentType.JSON));

        }
        //3.发送请求
        client.bulk(request,RequestOptions.DEFAULT);
    }



    @Test
    void testUpdateDocumentById() throws IOException {
        //1.准备Request
        UpdateRequest request = new UpdateRequest("hotel", "36934");
        //2.准备请求参数
        request.doc(
                "price","952",
                "starName","五钻"
        );
        //2.发送请求,得到响应
        client.update(request, RequestOptions.DEFAULT);
        //3.解析响应结果
    }

    @Test
    void testDeleteDocumentById() throws IOException {

        List<Hotel> list = hotelService.list();
        //循环删除
        for ( Hotel hotel : list ) {
            //1.准备Request
            DeleteRequest request = new DeleteRequest("hotel", hotel.getId().toString());

            //2.发送请求,得到响应
            client.delete(request, RequestOptions.DEFAULT);
        }

        //1.准备Request
        DeleteRequest request = new DeleteRequest("hotel", "36934");

        //2.发送请求,得到响应
        client.delete(request, RequestOptions.DEFAULT);

    }





    @BeforeEach
    void setUp(){
        this.client = new RestHighLevelClient(
                RestClient.builder(HttpHost.create("http://虚机机地址:es端口")
                ));
    }

    @AfterEach
    void tearDown()throws IOException{
        this.client.close();
    }
}

DSL 查询文档

 

 DSL  Query的分类

DSL Query基本语法

 全文检索查询


GET /hotel/_doc/36934

#查询所有
GET /hotel/_search
{
  "query": {
    "match_all": {}
  }
}

#math查询
GET /hotel/_search
{
  "query": {
    "match": {
      "all": "外滩如家"
    }
  }
}

#multi_math查询
GET /hotel/_search
{
  "query": {
    "multi_match": {
      "query": "外滩如家",
      "fields": ["brand","name","business"]
    }
  }
}

 精确查询

 

#term查询
GET /hotel/_search
{
  "query": {
    "term": {
      "city": {
        "value": "上海"
      }
    }
  }
}

#range查询 几个e代表等于
GET /hotel/_search
{
  "query": {
    "range": {
      "price": {
        "gte": 1000,
        "lte": 3000
      }
    }
  }
}

 地理查询

 

 

#distance查询
GET /hotel/_search
{
  "query": {
    "geo_distance": {
      "distance":"3km",
      "location":"31.219306, 121.445427"
    }
  }
}

相关性算分

 

 Function Score Query

#function score 查询
GET /hotel/_search
{
  "query": {
    "function_score": {
      "query": {
        "match": {
          "all": "外滩"
        }
      },
      "functions": [
        {
          
          "filter":{
            "term":{
              "brand":"7天酒店"
            }
          },
          "weight":10
        }
       ],
       "boost_mode":"sum"
      }
    }
  }
 }
}

 

复合查询 Boolean Query

 

GET /hotel/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "如家"
          }
        }
      ],
      "must_not": [
        {
          "range": {
            "price": {
              "gt": 400
             
            }
          }
        }
      ],
      "filter": [
        {
          "geo_distance": {
            "distance": "10km",
            "location": {
              "lat": 31.21,
              "lon": 121.5
            }
          }
        }
      ]
    }
  }
}
 

 搜索结果处理

排序


#sort排序
GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
        "score": "desc"
      
    },
    {
      "price": "asc" 
    }
    
  ]
}

#找到121.6122,31.034周围的酒店,距离升序排序
GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "_geo_distance": {
        "location": {
          "lat": 31.034,
          "lon": 121.6122
        },
        "order": "asc",
        "unit": "km"
      }
    }
  ]
}

分页

深度分页问题

 

高亮 

 



#分页查询
GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
        "price": "asc" 
      
    }
  ],
   "from":10,
    "size":10
}

#高亮显示 默认情况,ES搜索字段必须与高亮字段一致
GET /hotel/_search
{
  "query": {
    "match": {
      "all": "如家"
    }
  },
  "highlight": {
    "fields": {
      "name":{
        "require_field_match": "false"
      }
    }
  }
}

RestClient查询文档

 

 

 

 

全文检索查询

 

精确查询 

符合查询

排序和分页

 ​​​​​​​高亮

 ​​​​​​​

觉得好的小伙伴记得一键三连哦


public class HotelIsearchTest {
    private RestHighLevelClient client;



    @Test
    void testMatchAll() throws IOException {
        //1 准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source()
                .query(QueryBuilders.matchAllQuery());
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4解析响应
        handleRequest(response);
    }

    /**
     * 全文检索查询
     * @throws IOException
     */
    @Test
    void testMatch() throws IOException {
        //1 准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        request.source()
                .query(QueryBuilders.matchQuery("all","如家"));
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        handleRequest(response);
    }

    /**
     * 精确查询、复合查询
     * @throws IOException
     */
    @Test
    void testBool() throws IOException {
        //1 准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        //2.1准备BooleanQuery
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        //2.2添加term
        boolQuery.must(QueryBuilders.termQuery("city","上海"));
        //2.3添加range
        boolQuery.filter(QueryBuilders.rangeQuery("price").lte(250));
        request.source()
                .query(boolQuery);
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        handleRequest(response);
    }

    /**
     * 排序和分页
     * @throws IOException
     */
    @Test
    void testPageAndSort() throws IOException {
        //页码、每页大小
        int page = 2,size = 5;
        //1 准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        //2.1query
        request.source()
                .query(QueryBuilders.matchAllQuery());
        //2.2排序sort
        request.source().sort("price", SortOrder.ASC);
        //2.3分页from、size
        request.source().from((page-1) * size).size(5);
        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        handleRequest(response);
    }

    /**
     * 高亮
     * @throws IOException
     */
    @Test
    void testHighlight() throws IOException {

        //1 准备Request
        SearchRequest request = new SearchRequest("hotel");
        //2.准备DSL
        //2.1query
        request.source()
                .query(QueryBuilders.matchQuery("all","如家"));
        //2.2高亮
        request.source()
                .highlighter(
                        new HighlightBuilder()
                                .field("name")
                                .requireFieldMatch(false)
                );

        //3.发送请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        handleHighlight(response);
    }


    private void handleRequest(SearchResponse response) {
        //4解析响应
        SearchHits searchHits = response.getHits();
        //4.1 获取总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到" + total + "条数据");
        //4.2文档数组
        SearchHit[] hits = searchHits.getHits();
        //4.3遍历
        for ( SearchHit hit : hits ) {
            //获取文档source
            String json = hit.getSourceAsString();
            //反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            System.out.println("hotelDoc = " + hotelDoc);
        }
        System.out.println(response);
    }

    /**
     * 高亮结果分析
     * @param response
     */
    private void handleHighlight(SearchResponse response) {
        //4解析响应
        SearchHits searchHits = response.getHits();
        //4.1 获取总条数
        long total = searchHits.getTotalHits().value;
        System.out.println("共搜索到" + total + "条数据");
        //4.2文档数组
        SearchHit[] hits = searchHits.getHits();
        //4.3遍历
        for ( SearchHit hit : hits ) {
            //获取文档source
            String json = hit.getSourceAsString();
            //反序列化
            HotelDoc hotelDoc = JSON.parseObject(json, HotelDoc.class);
            //获取高亮结果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            if ( !CollectionUtils.isEmpty(highlightFields) ) {
                //根据字段名获取如果
                HighlightField highlightField = highlightFields.get("name");
                if ( highlightField!=null ) {
                    //获取高亮的值
                    String name = highlightField.getFragments()[0].string();
                    //覆盖非高亮结果
                    hotelDoc.setName(name);
                }

            }

            System.out.println("hotelDoc = " + hotelDoc);
        }
        System.out.println(response);
    }

    /**
     *  高亮结果解析
     */

    @BeforeEach
    void setUp(){
        this.client = new RestHighLevelClient(
                RestClient.builder(HttpHost.create("http://虚拟机地址:es端口号")
                ));
    }

    @AfterEach
    void tearDown()throws IOException{
        this.client.close();
    }
}

  • 5
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值