1、介绍
使用elasticsearch技术实现商品搜索功能,相对mysql,效率更高,分词查找更合理!
2、声明配置
- bootstrap.yml
spring:
application:
name: search-service
cloud:
nacos:
server-addr: 120.221.70.206:8848
server:
port: 3007
- application.yml
ribbon:
eager-load:
enabled: true #开启饥饿加载提升第一次访问速度
clients:
- search-service #指定开启服务
feign:
httpclient:
enabled: true # 开启httpClient开关,启动连接池,提升feign连接效率!
max-connections: 200 #最大连接数量
max-connections-per-route: 50 #单路径最大连接数
- 配置启动类
//排除自动导入数据库配置,否者出现为配置连接池信息异常
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
DruidDataSourceAutoConfigure.class ,
HibernateJpaAutoConfiguration.class}).
public class SearchApplication {
public static void main(String[] args) {
System.out.println("SearchApplication.main-----");
SpringApplication.run(SearchApplication.class,args);
System.out.println("SearchApplication.main+++++");
}
}
-
添加网关配置
store-gateway中,添加网关配置
- id: search-service # 类别服务
uri: lb://search-service
predicates:
- Path=/search/**
3、功能实现
3.1 同步数据
1. 监控查询服务启动
2. 每次启动,进行es数据整体更新
3. 商城后台管理商品修改删除添加,出发更新
3.2 搜索功能
3.2.1 准备dsl语句 [相当于数据库的表]
准备商品索引创建DSL语句!
将商品名,标题以及详细描述,添加到all字段,直接使用all字段搜索即可!
!!! 不在单独进行搜索,提高查询效率!
# 删除索引结构
DELETE /product
# 创建商品索引!
# 根据多列搜索性能较差,组成成一列搜索提高性能
PUT /product
{
"mappings": {
"properties": {
"productId":{
"type": "integer"
},
"productName":{
"type": "text",
"analyzer": "ik_smart",
"copy_to": "all"
},
"categoryId":{
"type": "integer"
},
"productTitle":{
"type": "text",
"analyzer": "ik_smart",
"copy_to": "all"
},
"productIntro":{
"type":"text",
"analyzer": "ik_smart",
"copy_to": "all"
},
"productPicture":{
"type": "keyword",
"index": false
},
"productPrice":{
"type": "double",
"index": true
},
"productSellingPrice":{
"type": "double"
},
"productNum":{
"type": "integer"
},
"productSales":{
"type": "integer"
},
"all":{
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
#查询索引
GET /product/_mapping
#全部查询
GET /product/_search
{
"query": {
"match_all": {
}
}
}
#关键字查询
GET /product/_search
{
"query": {
"match": {
"all": "最好"
}
}
}
# 关键字 和 添加分页
GET /product/_search
{
"query": {
"match": {
"all": "最好"
}
},
"from": 0,
"size": 1
}
# 添加数据
POST /product/_doc/1
{
"productId":1,
"productName":"雷碧",
"productTitle":"最好的碳酸饮料",
"categoryId":1,
"productIntro":"硫酸+煤炭制品最好的产品!",
"productPicture":"http://www.baidu.com",
"productPrice":10.5,
"productSellingPrice":6.0,
"productNum":10,
"productSales":5
}
# 删除数据
DELETE /product/_doc/1
3.2.2 定义doc模型
用来存储商品搜索数据的实体类
3.3 Rabbitmq配置
-
业务需求
- 对es商品数据进行删除、添加(覆盖更新)场景消息通信
- 后台管理模块添加,修改商品发送更新指令
- 后台管理删除删除商品发送删除指令
- 监听消息,实现es的数据更新和删除
-
交换机和消息key关系
-
store-commons声明mq配置
-
介绍
使用消息队列的服务配置全一致,所以声明到通用模块,需要使用的服务,只需要导入此模块,激活配置即可!
-
application-mq.yml
-
spring:
rabbitmq:
host: 124.221.70.206
port: 5672
virtual-host: /
username: root
password: 123456
listener:
simple:
prefetch: 1 # 预先分配1个 能者多劳
- 修改application.yml
spring:
profiles:
active: mq # 激活配置
-
rabbit配置配置类
配置示例
/**
* 演示,注解方式,在消息消费者位置完成 交换机队列关系绑定!
* @param data
*/
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "insert.queue"),
exchange = @Exchange("topic.ex"),
key = "insert.product"
))
public void insert(Map data){
System.out.println("SpringRabbitListener.insert");
System.out.println("data = [" + data + "]");
}
3.4更新数据
@Component
public class RabbitMQListener {
@Autowired
private RestHighLevelClient client;
/**
* 更新和插入数据同一个!
*/
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "insert.queue"),
exchange = @Exchange("topic.ex"),
key = "insert.product"
))
public void insert(Product product) throws IOException {
IndexRequest indexRequest = new IndexRequest("product")
.id(product.getProductId().toString());
ProductDoc productDoc = new ProductDoc(product);
ObjectMapper objectMapper = new ObjectMapper();
String json = objectMapper.writeValueAsString(productDoc);
indexRequest.source(json, XContentType.JSON);
client.index(indexRequest, RequestOptions.DEFAULT);
}
}
3.5 删除数据
/**
* 删除数据
* @param productId
*/
@RabbitListener(bindings = @QueueBinding(
value = @Queue(name = "delete.queue"),
exchange = @Exchange("topic.ex"),
key = "delete.product"
))
public void remove(Integer productId) throws IOException {
DeleteRequest request = new DeleteRequest("product")
.id(productId.toString());
client.delete(request,RequestOptions.DEFAULT);
}