目录
3.3 dockerfile与dockercompose的使用
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"
}
}
]
}