提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
仅个人笔记!
提示:以下是本篇文章正文内容,下面案例可供参考
一、ES是什么?
ES(Elasticsearch)是一个基于RESTful web接口并且构建在Apache Lucene之上的开源分布式搜索引擎。它不仅是一个功能强大的搜索引擎,还具备分布式文档数据库的特性,能够处理PB级的数据
二、使用步骤
1.依赖
代码如下(示例):
<!-- es --> <dependency> <groupId>org.elasticsearch.client</groupId> <artifactId>elasticsearch-rest-high-level-client</artifactId> </dependency>
2.配置类
代码如下(示例):
@Configuration @ConfigurationProperties(prefix = "es") @Data public class InitEsRes { private String host; private int port; private String scheme; @Bean public RestHighLevelClient restHighLevelClient(){ return new RestHighLevelClient( RestClient.builder(new HttpHost(host,port,scheme)) ); } }
@Configuration @ConfigurationProperties(prefix = "es") @Data public class InitESRestHighLevelClient { /** * es服务 地址 */ private String host; /** * 端口 */ private int port; /** * 请求方式 */ private String scheme; /** * 构建 RestHighLevelClient 用来做 es 操作 * @return */ @Bean public RestHighLevelClient restHighLevelClient() { return new RestHighLevelClient( RestClient.builder(new HttpHost(host, port, scheme)) ); } }
3.实现方法(模糊查询、高亮、分类、排序、批量添加)
代码如下(示例):
@Service @Slf4j public class IESSpuInfoServiceImpl implements IESSpuInfoService { @Autowired private RestHighLevelClient restHighLevelClient; private static final String INDEX_NAME = "product_info"; private static final String NAME = "spuName"; @Override public List<PmsSpuInfoVO> esSpuInfoList(String keywords) { ArrayList<PmsSpuInfoVO> list = new ArrayList<>(); SearchRequest searchRequest = new SearchRequest(INDEX_NAME); SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder(); searchRequest.source(searchSourceBuilder); BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder(); if (StringUtils.isNotBlank(keywords)){ boolQueryBuilder.must(QueryBuilders.matchQuery(NAME,keywords)); } searchSourceBuilder.highlighter( new HighlightBuilder() .field(NAME) .preTags("<span style = \"color:red\">") .postTags("</span>") ); // 分类 TermsAggregationBuilder aggregation = AggregationBuilders.terms("brand_id").field("brandId"); searchSourceBuilder.aggregation(aggregation); // 排序 searchSourceBuilder.sort(SortBuilders.fieldSort("lastUpdatedTime").order(SortOrder.ASC)); searchSourceBuilder.query(boolQueryBuilder); try { searchRequest.source(searchSourceBuilder); SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT); SearchHits hits = searchResponse.getHits(); SearchHit[] searchHits = hits.getHits(); for (SearchHit searchHit : searchHits) { String sourceAsString = searchHit.getSourceAsString(); PmsSpuInfoVO warranty = JSONObject.parseObject(sourceAsString, PmsSpuInfoVO.class); Map<String, HighlightField> highlightFields = searchHit.getHighlightFields(); if (highlightFields!=null){ HighlightField highlightField = highlightFields.get(NAME); if (highlightField!=null){ Text[] fragments = highlightField.getFragments(); StringBuffer stringBuffer = new StringBuffer(); for (Text fragment : fragments) { stringBuffer.append(fragment); } warranty.setSpuName(stringBuffer.toString()); } } list.add(warranty); } }catch (Exception e){ log.info("错误:",e); } return list; } @Override public void updateProductInfo(List<PmsSpuInfoVO> updatedProducts) { BulkRequest bulkRequest = new BulkRequest(); updatedProducts.forEach(pmsSpuInfoVO -> { bulkRequest.add( new IndexRequest(INDEX_NAME) .id(pmsSpuInfoVO.getId().toString()) .source(JSON.toJSONString(pmsSpuInfoVO), XContentType.JSON)); }); try { BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT); System.out.println(bulkResponse.status()); } catch (IOException e) { e.printStackTrace(); } } }
拓展
(定时任务)根据时间判断通过mq将数据存es列表
1.依赖
代码如下(示例):
<!-- rabbitMQ --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-amqp</artifactId> </dependency>
2.配置类
代码如下(示例):
package com.shop.pms.config; import org.springframework.amqp.core.DirectExchange; import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; import org.springframework.amqp.support.converter.MessageConverter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class RabbitmqConfig { // 消息转换配置 @Bean public MessageConverter jsonMessageConverter() { return new Jackson2JsonMessageConverter(); } @Bean public DirectExchange productExchange() { // 创建一个名为productName的直连交换机,并设置为持久化 return new DirectExchange("productName", true, false); } }
package com.shop.pms.config; import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; import org.springframework.amqp.rabbit.connection.ConnectionFactory; import org.springframework.amqp.rabbit.core.RabbitAdmin; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * rabbitAdmin 配置类 用来构建 RabbitAdmin */ @Configuration public class RabbitAdminConfig { @Value("${spring.rabbitmq.host}") private String host; @Value("${spring.rabbitmq.username}") private String username; @Value("${spring.rabbitmq.password}") private String password; @Value("${spring.rabbitmq.virtualHost}") private String virtualhost; @Bean public ConnectionFactory connectionFactory() { CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); connectionFactory.setAddresses(host); connectionFactory.setUsername(username); connectionFactory.setPassword(password); connectionFactory.setVirtualHost(virtualhost); // 设置消息发送确认 connectionFactory.setPublisherConfirmType(CachingConnectionFactory.ConfirmType.CORRELATED); connectionFactory.setPublisherReturns(true); //我们将填充好的 cachingConnectionFactory 实例进行返回,以初始化完成 RabbitMQ 客户端连接 return connectionFactory; } @Bean public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) { RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory); rabbitAdmin.setAutoStartup(true); return rabbitAdmin; } }
package com.shop.pms.config; import org.springframework.amqp.core.ReturnedMessage; import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; /** * 消息发送到队列的确认 */ @Component public class ReturnCallbackConfig implements RabbitTemplate.ReturnsCallback { @Autowired private RabbitTemplate rabbitTemplate; @PostConstruct // @PostContruct是spring框架的注解,在⽅法上加该注解会在项⽬启动的时候执⾏该⽅法,也可以理解为在spring容器初始化的时候执 public void init() { rabbitTemplate.setReturnsCallback(this); } /** * 消息发送到 队列失败的时候执行 * @param returnedMessage the returned message and metadata. */ @Override public void returnedMessage(ReturnedMessage returnedMessage) { System.out.println("消息" + returnedMessage.getMessage().toString() + "被交换机" + returnedMessage.getExchange() + "回退!" + "退回原因为:" + returnedMessage.getReplyText()); // TODO 回退了所有的信息,可做补偿机制 } }
3.实现方法
代码如下(示例):
@Override public List<PmsSpuInfoVO> productInfoList() { List<PmsSpuInfoVO> productInfoList = mainPageMapper.productInfoList(); // 计算30分钟前的时间 Date thirtyMinutesAgo = new Date(System.currentTimeMillis() - 30 * 60 * 1000); // 过滤最近30分钟内更新的产品 List<PmsSpuInfoVO> updatedProducts = productInfoList.stream() .filter(product -> product.getLastUpdatedTime().after(thirtyMinutesAgo)) .collect(Collectors.toList()); // 发送RabbitMQ消息 if (!updatedProducts.isEmpty()) { log.info("发送数据几条:{}", updatedProducts.size()); rabbitTemplate.convertAndSend("productSpuInfo", updatedProducts); } else { log.info("没有产品在最近30分钟内更新"); } return productInfoList; }
@Component @Slf4j public class MessageConsumer { @Autowired private IESSpuInfoService esSpuInfoService; @RabbitListener(queuesToDeclare =@Queue("productSpuInfo")) public void handleProductMessage(List<PmsSpuInfoVO> pmsSpuInfoVOList) { if (pmsSpuInfoVOList == null || pmsSpuInfoVOList.isEmpty()) { log.warn("Received an empty or null list of product info. Skipping..."); return; } try { log.info("Starting to update product info for {} items", pmsSpuInfoVOList.size()); esSpuInfoService.updateProductInfo(pmsSpuInfoVOList); log.info("Successfully updated product info for {} items", pmsSpuInfoVOList.size()); } catch (Exception e) { log.error("Error updating product info", e); // 根据业务需求,可以选择重新抛出异常或者进行其他补偿措施 throw new RuntimeException("Failed to update product info", e); } } }
4.定时任务实现方法
代码如下(示例):
@Component @Slf4j public class SyncService { @Autowired private IMainPageServiceImpl iMainPageService; // @Scheduled(fixedRate = 100) // 测试使用 @Scheduled(fixedRate = 1800000) // 每30分钟执行一次 public void syncDataToES() { List<PmsSpuInfoVO> productInfoList = iMainPageService.productInfoList(); log.info(productInfoList.toString()); } }