SpringCloud学习笔记

目录

day01

1.1 利用restTemplate实现服务之间的远程调用

1.2 euraka注册中心实现服务注册与发现

1.3 负载均衡原理与策略-Ribbon

1.3 Nacos注册中心实现服务注册与发现

day02

2.1 nacos配置

2.2 feign代替restTemplate实现远程调用

feign的性能优化-使用http连接池

feign的最佳实践

2.3 gateway实现网关

day03

3.1 docker的安装与使用

3.1.1docker常用命令

3.2 docker数据卷的创建与使用

3.3 dockerfile与dockercompose的使用 

day04

4.1 rabbitmq的安装与使用

4.2 官方接口代码

4.3 利用Spring简化官方接口代码

4.4 工作队列模型

day05

5.1 elasticsearch的安装与使用

5.2 kibana的安装与使用

5.3 IK分词器的安装与使用

5.4 创建索引表并操作

 5.5 创建文档并操作

5.6 利用java操作es


day01

1.1 利用restTemplate实现服务之间的远程调用

项目包结构

 核心代码

配置restTemplate

package cn.itcast.order;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@MapperScan("cn.itcast.order.mapper")
@SpringBootApplication
public class OrderApplication {

    public static void main(String[] args) {
        SpringApplication.run(OrderApplication.class, args);
    }

    @Bean
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

}

利用restTemplate发送http请求访问user模块提供的查询用户接口

package cn.itcast.order.service;

import cn.itcast.order.mapper.OrderMapper;
import cn.itcast.order.pojo.Order;
import cn.itcast.order.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private RestTemplate restTemplate;

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.发送http请求
        // 2.1 url路径
        String url = "http://localhost:8081/user/" + order.getUserId();
        // 2.2 获取user信息
        User user = restTemplate.getForObject(url, User.class);
        // 3.将user信息注入order对象
        order.setUser(user);
        // 4.返回
        return order;
    }
}

1.2 euraka注册中心实现服务注册与发现

创建一个新的module,取名为eureka-server

配置eureka依赖

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

编写springboot主函数

package cn.itcast.eureka;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * @author bilibilidick
 * @version 2022 07
 * @date 2022/7/7 12:36
 */
@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }

}

编写配置文件

server.port=10086
spring.application.name=eureka_server
eureka.client.service-url.defaultZone=http://localhost:10086/eureka

启动eureka微服务

在orderservice与userservice模块中引入eureka-client依赖

<!--        eureka客户端依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

并同时修改配置文件,进行服务的注册

eureka:
  client:
    service-url:
      defaultZone: "http://localhost:10086/eureka"
spring:
  application:
    name: orderservice || userservice

增加userservice实例之后重新启动查看eureka网页

 

修改orderserviceimp调用userservice模块的代码,改为springapplicationname的属性名

package cn.itcast.order.service;

import cn.itcast.order.mapper.OrderMapper;
import cn.itcast.order.pojo.Order;
import cn.itcast.order.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private RestTemplate restTemplate;

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.发送http请求
        // 2.1 url路径
        String url = "http://userservice/user/" + order.getUserId();
        // 2.2 获取user信息
        User user = restTemplate.getForObject(url, User.class);
        // 3.将user信息注入order对象
        order.setUser(user);
        // 4.返回
        return order;
    }
}

利用postman发送两次请求

 

 可看到负载均衡的效果

1.3 负载均衡原理与策略-Ribbon

 

 通过配置orderservice的IRule修改orderservice的全局负载均衡规则,修改为随机规则

   @Bean
    public IRule randomRule() {
        return new RandomRule();
    }

 或者修改orderservice的配置文件来修改局部的负载均衡规则

userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则

更改Ribbon的加载方式为饥饿加载

在orderservice第一次访问userservice服务时,响应时间较长

后续访问响应时间较短

原因是ribbon未开启饥饿加载,在第一次访问userservice服务时才会创建负载均衡器

 故更改orderservice配置文件

ribbon:
  eager-load:
    enabled: true
    clients:
      - userservice

 后续再重新启动orderservice,在第一次访问userservice时可看到响应时间缩短一半

1.3 Nacos注册中心实现服务注册与发现

在父工程下配置spring-cloud-alibaba-dependencies

            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
                <version>2.2.5.RELEASE</version>
                <scope>import</scope>
                <type>pom</type>
            </dependency>

在子工程下配置spring-cloud-starter-alibaba-nacos-discovery

       <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>

在子工程的配置文件下配置nacos服务端地址

spring:
   cloud:
    nacos:
      server-addr: localhost:8848

启动nacos

 

 进行访问测试

 结果正常

 nacos实现优先访问集群的负载均衡模式

配置好orderservice与userservice的集群

spring:
    cloud:
      discovery:
        cluster-name: FJ

 userservice集群分布,orderservice集群也为FJ

 改变orderservice访问userservice的负载均衡模式

userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule # 负载均衡规则

测试请求可知orderservice优先访问同集群下的userservice服务

 

 跨集群访问会出现警告信息

nacos的集群结点权重设置

 nacos的namespace设置,不同命名空间的结点无法相互访问


spring:
  datasource:
    url: jdbc:mysql://localhost:3306/cloud_order?useSSL=false
    username: root
    password: a
    driver-class-name: com.mysql.jdbc.Driver
  application:
    name: orderservice
  cloud:
    nacos:
      server-addr: localhost:8848
      discovery:
        cluster-name: FJ
#        namespace: 7a9e5a3d-008b-4f4b-9df3-63c1aece249c



















day02

2.1 nacos配置

打开nacos网站编辑配置文件,文件名格式为服务名-环境名.后缀名

 引入nacos配置的依赖

<!--        nacos配置依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
        </dependency>

在userservice创建一个名为bootstrap.yml的文件,此文件先于application.yml前执行,故在此做nacos的配置文件的配置

spring:
  application:
    name: userservice
  cloud:
    nacos:
      server-addr: localhost:8848
      config:
        file-extension: yaml
  profiles:
    active: dev

修改usercontroller的代码

package cn.itcast.user.web;

import cn.itcast.user.pojo.User;
import cn.itcast.user.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.context.annotation.Scope;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Slf4j
@RefreshScope
@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @Value("${pattern.dateformat}")
    private String dateFormat;

    /**
     * 路径: /user/110
     *
     * @param id 用户id
     * @return 用户
     */
    @GetMapping("/{id}")
    public User queryById(@PathVariable("id") Long id) {
        return userService.queryById(id);
    }


    @GetMapping("/now")
    public String getLocalTime() {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateFormat));
    }
}

postman返回结果,可随nacos配置文件的更改而改变内容,无需重启服务 

2.2 feign代替restTemplate实现远程调用

引入openfeign的依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

创建对于user服务的feign接口

package cn.itcast.order.feign;

import cn.itcast.order.pojo.User;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @author bilibilidick
 * @version 2022 07
 * @date 2022/7/10 15:52
 */
@FeignClient("userservice")
public interface UserClient {

    @GetMapping("user/{id}")
    User getUser(@PathVariable("id") Long id);

}

在main函数上标注注解

@EnableFeignClients

修改orderservice的代码,替换为feign实现远程调用

package cn.itcast.order.service;

import cn.itcast.order.feign.UserClient;
import cn.itcast.order.mapper.OrderMapper;
import cn.itcast.order.pojo.Order;
import cn.itcast.order.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class OrderService {

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private UserClient userClient;

    public Order queryOrderById(Long orderId) {
        // 1.查询订单
        Order order = orderMapper.findById(orderId);
        // 2.发送http请求
        // 2.1 url路径
        //String url = "http://userservice/user/" + order.getUserId();
        // 2.2 获取user信息
        //User user = restTemplate.getForObject(url, User.class);
        User user = userClient.getUser(order.getUserId());
        // 3.将user信息注入order对象
        order.setUser(user);
        // 4.返回
        return order;
    }
}

feign的性能优化-使用http连接池

引入依赖

        <dependency>
            <groupId>io.github.openfeign</groupId>
            <artifactId>feign-httpclient</artifactId>
        </dependency>

配置连接池

feign:
  client:
    config:
      default:
        loggerLevel: BASIC
  httpclient:
    enabled: true
    max-connections: 200
    max-connections-per-route: 50

feign的最佳实践

创建一个新的module

在orderservice的主函数上更新注解

@EnableFeignClients(clients = UserClient.class)

2.3 gateway实现网关

创建一个新的模块并引入nacos服务注册依赖与网关依赖

<!--        服务发现与注册依赖-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!--网关依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-gateway</artifactId>
        </dependency>

配置文件

server:
  port: 10010
spring:
  application:
    name: gateway
  cloud:
    nacos:
      server-addr: localhost:8848
    gateway:
      routes:
        - id: user-service
          uri: lb://userservice
          predicates:
            - Path=/user/**

利用postman测试网关

网关过滤器添加请求头

 全局网关过滤器,与默认网关过滤器的区别在于可用户自定义

网关解决分布式跨域问题









day03

3.1 docker的安装与使用

安装yum-utils

yum install -y yum-utils \
> device-mapper-persistent-data\
> lvm2 --skip-broken

配置yum的下载源

yum-config-manager \
    --add-repo \
    https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
    
sed -i 's/download.docker.com/mirrors.aliyun.com\/docker-ce/g' /etc/yum.repos.d/docker-ce.repo

yum makecache fast

要注意centos8没有yum makecache fast,要把这行删掉

之后输入命令开始安装docker-ce版本

yum install -y docker-ce

由于docker应用需要用到各种端口,逐一配置防火墙略显繁琐,故直接关闭防火墙

# 关闭
systemctl stop firewalld
# 禁止开机启动防火墙
systemctl disable firewalld

启动docker

systemctl start docker  # 启动docker服务

 

 配置docker的镜像加速

参考阿里云镜像加速文档

3.1.1docker常用命令

拉取nginx镜像,不指定镜像版本默认拉取latest

docker pull nginx

查看当前拥有的镜像

docker images

 将镜像导出为文件

docker save -o nginx.tar nginx:latest

删除docker中的nginx镜像

docker rmi nginx:latest

读取nginx.tar

docker load -i nginx.tar

运行nginx容器

docker run --name mn -p 80:80 -d nginx:latest

运行成功!

 在浏览器上查看结果,访问成功!!

docker查看日志

docker logs mn

3.2 docker数据卷的创建与使用

输入命令

docker volume create html

查看创建好的数据卷

docker volume ls

 挂载数据卷

docker run --name mn -p 80:80 -v html:/usr/share/nginx/html -d nginx:latest

修改数据卷中的html内容

 修改成功

3.3 dockerfile与dockercompose的使用 

基于java8的镜像基础上编写dockerfile

输入命令构建自定义镜像,.表示当前目录下的DockerFile文件

docker build -t javaweb:1.0 .

 

 利用镜像运行docker容器

docker run --name web -p 8090:8090 -d javaweb:1.0

 通过浏览器访问8090端口,访问成功






day04

4.1 rabbitmq的安装与使用

利用docker拉取rabbitmq

docker pull rabbitmq:3-management

运行以下命令来启动rabbitmq,其中15672是管理员界面端口,5672是服务调用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

4.2 官方接口代码

生产者的官方接口示例代码

package cn.itcast.mq.helloworld;

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import org.junit.Test;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class PublisherTest {
    @Test
    public void testSendMessage() throws IOException, TimeoutException {
        // 1.建立连接
        ConnectionFactory factory = new ConnectionFactory();
        // 1.1.设置连接参数,分别是:主机名、端口号、vhost、用户名、密码
        factory.setHost("112.74.72.126");
        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();

    }
}

消费者的官方接口示例代码

package cn.itcast.mq.helloworld;

import com.rabbitmq.client.*;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

public class ConsumerTest {

    public static void main(String[] args) throws IOException, TimeoutException {
        // 1.建立连接
        ConnectionFactory factory = new ConnectionFactory();
        // 1.1.设置连接参数,分别是:主机名、端口号、vhost、用户名、密码
        factory.setHost("112.74.72.126");
        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.订阅消息
        channel.basicConsume(queueName, true, new DefaultConsumer(channel){
            @Override
            public void handleDelivery(String consumerTag, Envelope envelope,
                                       AMQP.BasicProperties properties, byte[] body) throws IOException {
                // 5.处理消息
                String message = new String(body);
                System.out.println("接收到消息:【" + message + "】");
            }
        });
        System.out.println("等待接收消息。。。。");
    }
}

4.3 利用Spring简化官方接口代码

配置消费者与生产者的配置文件

spring:
  rabbitmq:
    host: 112.74.72.126 # rabbitMQ的ip地址
    port: 5672 # 端口
    username: itcast
    password: 123321
    virtual-host: /

利用Spring编写rabbitmq的消费者

@Component
public class SpringRabbitListener {

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

利用Spring编写rabbitmq的生产者

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

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

4.4 工作队列模型

生产者代码,一次性发送50条消息

    @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);
        }
    }

修改消费者配置文件,配置为一次只取一条消息

spring:
  rabbitmq:
    host: 112.74.72.126 # rabbitMQ的ip地址
    port: 5672 # 端口
    username: itcast
    password: 123321
    virtual-host: /
    listener:
      simple:
        prefetch: 1

消费者代码

@Component
public class SpringRabbitListener {


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

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

fanout模型就是加个交换机,生产者一发消息消费者都接收得到,topic模型还是类似加了交换机模型就是生产者与消费者之间存在暗号,消费者不会接收生产者发布的任何消息,而是有选择的接收。









day05

5.1 elasticsearch的安装与使用

倒排索引图解

要注意虽然es没有定义数组类型,但是允许每个数值类型都作为数组

拉取es镜像

docker pull elasticsearch:7.12.1

拉取elasticsearch镜像后运行容器

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

进入浏览器访问9200端口,启动成功!

5.2 kibana的安装与使用

安装kibana

docker pull kibana:7.12.1

运行kibana,并将其纳入与es相同的网络中

docker run -d \
 --name kibana \
 -e ELASTICSEARCH_HOSTS=http://es:9200 \
 --network=es-net \
 -p 5601:5601 \
 kibana:7.12.1

进入浏览器后发送DSL请求

 测试分词效果,可知默认分词器只支持英文不支持中文

5.3 IK分词器的安装与使用

安装ik分词器

将ik分词器解压后挂载到plugin的数据卷上,新建一个名为ik的文件夹放入

 重启es容器后查看es日志,可知es容器已加载ik分词器!

测试ik_smart模式下的ik分词器效果,分词效果良好

测试id_max_word模式下的ik分词器效果,分词效果良好

 添加新的分词与扩展停用词词典

首先进到挂载esconfig的数据卷,修改IKAnalyzer.cfg.xml这个文件

 修改为如下,其中ext.dic为分词扩展字典文件,stopword.dic为停用词扩展文件,默认位置为当前目录

 类似这样

 重启es容器,测试分词效果,分词效果良好

5.4 创建索引表并操作

PUT /heima
{
  "mappings": {
    "properties": {
      "info": {
        "type": "text",
        "analyzer": "ik_smart"
      },
      "email": {
        "type": "keyword",
        "index": false
      },
      "name": {
        "properties": {
          "firstName": {
            "type": "keyword"
          },
          "lastName": {
            "type": "keyword"
          }
        }
      }
    }
  }
}

kibana返回结果

 查询索引表

GET /heima

 删除索引表

DELETE /heima

修改索引表,

由于es几乎不允许用户修改索引表,所以只能新增索引 

PUT /heima/_mapping
{
  "properties": {
    "age": {
      "type": "keyword",
      "index": "false"
    }
  }
}

 5.5 创建文档并操作

增加一条文档

POST /heima/_doc/1
{
  "info": "2022年软考成绩还不出?",
  "email": "1143134686@qq.com",
  "name": {
    "firstName": "谢",
    "lastName": "建军"
  }
}

 查询此文档

GET /heima/_doc/1

全量修改文档,其实也可以用来做新增请求

局部修改文档

5.6 利用java操作es

新增索引表核心代码

    @Test
    void testCreate() throws IOException {
        CreateIndexRequest request = new CreateIndexRequest("hotel");
        request.source(MAPPING_TEMPLATE, XContentType.JSON);
        client.indices().create(request, RequestOptions.DEFAULT);
    }

    @BeforeEach
    void setUp() {
        client = new RestHighLevelClient(RestClient.builder(
                HttpHost.create("http://112.74.72.126:9200")
        ));
    }

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

在kibana上测试,成功输出 

删除索引表代码

    @Test
    void testDelete() throws IOException {
        DeleteIndexRequest request = new DeleteIndexRequest("hotel");
        client.indices().delete(request, RequestOptions.DEFAULT);
    }

 判断索引表是否存在代码

    @Test
    void testExist() throws IOException {
        GetIndexRequest request = new GetIndexRequest("hotel");
        System.out.println(client.indices().exists(request, RequestOptions.DEFAULT));
    }

单个文档插入索引库的操作

    @Test
    void testAddDocument() throws IOException {
        // 1.查询数据库hotel数据
        Hotel hotel = hotelService.getById(61083L);
        // 2.转换为HotelDoc
        HotelDoc hotelDoc = new HotelDoc(hotel);
        // 3.转JSON
        String json = JSON.toJSONString(hotelDoc);

        // 1.准备Request
        IndexRequest request = new IndexRequest("xiejianjunhotel").id(hotelDoc.getId().toString());
        // 2.准备请求参数DSL,其实就是文档的JSON字符串
        request.source(json, XContentType.JSON);
        // 3.发送请求
        client.index(request, RequestOptions.DEFAULT);
    }

多文档插入索引库的操作

 @Test
    void testBulkRequest() throws IOException {
        // 查询所有的酒店数据
        List<Hotel> list = hotelService.list();

        // 1.准备Request
        BulkRequest request = new BulkRequest();
        // 2.准备参数
        for (Hotel hotel : list) {
            // 2.1.转为HotelDoc
            HotelDoc hotelDoc = new HotelDoc(hotel);
            // 2.2.转json
            String json = JSON.toJSONString(hotelDoc);
            // 2.3.添加请求
            request.add(new IndexRequest("xiejianjunhotel").id(hotel.getId().toString()).source(json, XContentType.JSON));
        }

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

根据索引库名称与其文档id查询文档

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

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


5.7 DSL查询语法

5.7.1 分词查询之单field查询

根据可分词的field进行查询,但是只能根据单条field进行查询

 内部写上多条就会报错

5.7.2 单field查询小技巧

但是在之前创建索引的过程中,我们将business、brand、name这三个字段copy_to到了一个名为all的字段,所以可以这样查询,他就会根据这三个字段的分词结果进行倒排查询,这样会比之后介绍的多字段查询速度来得快

5.7.3 多field查询

5.7.4 精准查询

 也不支持多字段精准查询

 5.7.5 范围查询

5.7.6 坐标查询

 5.8 复合查询

5.8.1 相关性算分的算法

 5.8.2 复合之函数查询demo

查询all字段包含的三种字段中包含外滩如家的所有结果中,将business为外滩地区的文档的分数乘10

5.8.3 复合查询之Boolean查询demo

查询名字中包含如家并且价格低于400并且地理坐标位于(31.21,121.5)的10km之内的文档

可以搭配这函数查询写屎山

GET /xiejianjunhotel/_search
{
  "query": {
    "function_score": {
      "query": {
        "bool": {
          "must": [
            {
              "match": {
                "name": "如家"
              }
            }
          ],
          "must_not": [
            {
              "range": {
                "price": {
                  "gt": 400
                }
              }
            }
          ],
          "filter": [
            {
              "geo_distance": {
                "distance": "10km",
                "location": {
                  "lat": 31.21,
                  "lon": 121.5
                }
              }
            }
          ]
        }
      },
      "functions": [
        {
          "filter": {
            "term": {
              "business": "周浦康桥地区"
            }
          },
          "weight": 10
        }
      ],
      "boost_mode": "multiply"
    }
  }
  , "sort": [
    {
      "price": {
        "order": "desc"
      }
    }
  ]
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值