JavaWeb_LeadNews_Day7-ElasticSearch, Mongodb

JavaWeb_LeadNews_Day7-ElasticSearch, Mongodb

  • elasticsearch
    • 安装配置
  • app文章搜索
    • 创建索引库
    • app文章搜索
      • 思路分析
      • 具体实现
    • 新增文章创建索引
      • 思路分析
      • 具体实现
  • MongoDB
    • 安装配置
    • SpringBoot集成MongoDB
  • app文章搜索记录
    • 保存搜索记录
      • 思路分析
      • 具体实现
    • 查询搜索历史
    • 删除搜索历史
  • 搜索联想词
  • 来源
  • Gitee

elasticsearch

安装配置

https://blog.csdn.net/Y_cen/article/details/131856995

app文章搜索

创建索引库

  • 使用postman添加映射
    Put请求, Json格式 : http://192.168.174.133:9200/app_info_article
    {"mappings":{"properties":{"id":{"type":"long"},"publishTime":{"type":"date"},"layout":{"type":"integer"},"images":{"type":"keyword","index": false},"staticUrl":{"type":"keyword","index": false},"authorId": {"type": "long"},"authorName": {"type": "text"},"title":{"type":"text","analyzer":"ik_smart"},"content":{"type":"text","analyzer":"ik_smart"}}}
    }
    
  • 依赖
    <!--elasticsearch-->
    <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId><version>7.12.1</version>
    </dependency>
    <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-client</artifactId><version>7.12.1</version>
    </dependency>
    <dependency><groupId>org.elasticsearch</groupId><artifactId>elasticsearch</artifactId><version>7.12.1</version>
    </dependency>
    
  • 导入数据
    @Autowired
    private ApArticleMapper apArticleMapper;@Autowired
    private RestHighLevelClient restHighLevelClient;/*** 注意:数据量的导入,如果数据量过大,需要分页导入* @throws Exception*/
    @Test
    public void init() throws Exception {// 1. 查询所有符合条件的文章数据List<SearchArticleVo> searchArticleVos = apArticleMapper.loadArticleList();// 2. 批量导入到es索引库BulkRequest bulkRequest = new BulkRequest("app_info_article");for (SearchArticleVo searchArticleVo : searchArticleVos) {IndexRequest indexRequest = new IndexRequest().id(searchArticleVo.getId().toString()).source(JSON.toJSONString(searchArticleVo), XContentType.JSON);// 批量添加数据bulkRequest.add(indexRequest);}restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
    }
    

app文章搜索

思路分析

具体实现

  • 配置
    没有使用数据库, 所以无需数据源的自动配置
    spring:autoconfigure:exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
    elasticsearch:host: 192.168.174.133port: 9200
    
  • 业务代码
    @Service
    public class ArticleSearchServiceImpl implements ArticleSearchService {@Autowiredprivate RestHighLevelClient restHighLevelClient;/*** es文章分页检索* @param dto* @return*/@Overridepublic ResponseResult search(UserSearchDto dto) throws IOException {// 1. 检查参数if(dto == null || StringUtils.isBlank(dto.getSearchWords())){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}// 2. 设置查询条件SearchRequest searchRequest = new SearchRequest("app_info_article");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();// 布尔查询BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();// 2.1 关键字的分词之后查询QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(dto.getSearchWords()).field("title").field("content").defaultOperator(Operator.OR);boolQueryBuilder.must(queryStringQueryBuilder);// 2.2 查询小于mindate的数据RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishTime").lt(dto.getMinBehotTime().getTime());boolQueryBuilder.filter(rangeQueryBuilder);// 2.3 分页查询searchSourceBuilder.from(0);searchSourceBuilder.size(dto.getPageSize());// 2.4 按照发布时间倒序查询searchSourceBuilder.sort("publishTime", SortOrder.DESC);// 2.5 设置高亮 titleHighlightBuilder highlightBuilder = new HighlightBuilder();highlightBuilder.field("title");highlightBuilder.preTags("<font style='color: red; font-size: inherit;'>");highlightBuilder.postTags("</font>");searchSourceBuilder.highlighter(highlightBuilder);searchSourceBuilder.query(boolQueryBuilder);searchRequest.source(searchSourceBuilder);SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);// 3. 结果封装返回List<Map> list = new ArrayList();SearchHit[] hits = searchResponse.getHits().getHits();for (SearchHit hit : hits) {String json = hit.getSourceAsString();Map map = JSON.parseObject(json, Map.class);// 处理高亮if(hit.getHighlightFields() != null && hit.getHighlightFields().size() > 0){Text[] titles = hit.getHighlightFields().get("title").getFragments();String title = StringUtils.join(titles);// 高亮标题map.put("h_title", title);}else{// 原始标题map.put("h_title", map.get("title"));}list.add(map);}return ResponseResult.okResult(list);}
    }
    
  • 网关配置
    app端网关
    #搜索微服务
    - id: leadnews-searchuri: lb://leadnews-searchpredicates:- Path=/search/**filters:- StripPrefix= 1
    

新增文章创建索引

思路分析

具体实现

  • Producer
    SearchArticleVo需要静态地址, 所以需要在FreeMarker生成静态文章, 上传到MinIo之后再发送创建索引的消息
    @Service
    @Slf4j
    @Transactional
    public class ArticleFreemarkerServiceImpl implements ArticleFreemarkerService {...@Override@Asyncpublic void buildArticleToMinIO(ApArticle article, String content) {if(StringUtils.isNotBlank(content)) {...// kafka: 新增文章创建索引, 发送消息createArticleESIndex(article, content, path);}}@Autowiredprivate KafkaTemplate<String, String> kafkaTemplate;private void createArticleESIndex(ApArticle article, String content, String path) {SearchArticleVo searchArticleVo = new SearchArticleVo();BeanUtils.copyProperties(article, searchArticleVo);searchArticleVo.setContent(content);searchArticleVo.setStaticUrl(path);kafkaTemplate.send(ArticleConstants.ARTICLE_ES_SYNC_TOPIC, JSON.toJSONString(searchArticleVo));}
    }
    
  • Listener
    @Component
    @Slf4j
    public class SyncArticleListener {@Autowiredprivate RestHighLevelClient restHighLevelClient;@KafkaListener(topics = ArticleConstants.ARTICLE_ES_SYNC_TOPIC)public void onMessage(String message){if(StringUtils.isNotBlank(message)){log.info("SyncArticleListener, message={}", message);SearchArticleVo vo = JSON.parseObject(message, SearchArticleVo.class);IndexRequest indexRequest = new IndexRequest("app_info_article");indexRequest.id(vo.getId().toString());indexRequest.source(message, XContentType.JSON);try {restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);} catch (IOException e) {log.error("sync es error={}", e);throw new RuntimeException(e);}}}}
    

MongoDB

安装配置

# 拉取镜像
docker pull mongo
# 创建容器
docker run -di --name mongo -p 27017:27017 -v ~/data/mongodata:/data mongo

SpringBoot集成MongoDB

  • 依赖
    <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-mongodb</artifactId>
    </dependency>
    
  • 配置
    spring:data:mongodb:host: 192.168.174.133port: 27017database: leadnews-history
    
  • 使用
    public class MongoTest {@Autowiredprivate MongoTemplate mongoTemplate;//保存@Testpublic void saveTest(){ApAssociateWords apAssociateWords = new ApAssociateWords();apAssociateWords.setAssociateWords("黑马头条");apAssociateWords.setCreatedTime(new Date());mongoTemplate.save(apAssociateWords);}//查询一个@Testpublic void saveFindOne(){ApAssociateWords apAssociateWords = mongoTemplate.findById("64e46fd4f3a760442bf50527", ApAssociateWords.class);System.out.println(apAssociateWords);}//条件查询@Testpublic void testQuery(){Query query = Query.query(Criteria.where("associateWords").is("黑马头条")).with(Sort.by(Sort.Direction.DESC,"createdTime"));List<ApAssociateWords> apAssociateWordsList = mongoTemplate.find(query, ApAssociateWords.class);System.out.println(apAssociateWordsList);}@Testpublic void testDel(){mongoTemplate.remove(Query.query(Criteria.where("associateWords").is("黑马头条")),ApAssociateWords.class);}
    }
    

app文章搜索记录

保存搜索记录

思路分析

异步保存

保存数据

具体实现

public class ApUserSearchServiceImpl implements ApUserSearchService {@Autowiredprivate MongoTemplate mongoTemplate;/*** 保存用户搜索记录* @param keyword* @param userId*/@Override@Asyncpublic void insert(String keyword, Integer userId) {// 1. 查询当前用户的搜索关键词Query query = Query.query(Criteria.where("userId").is(userId).and("keyword").is(keyword));ApUserSearch apUserSearch = mongoTemplate.findOne(query, ApUserSearch.class);// 2. 存在, 更新创建时间if(apUserSearch != null){apUserSearch.setCreatedTime(new Date());mongoTemplate.save(apUserSearch);return;}// 3. 不存在, 判断当前历史记录总数量是否超过10apUserSearch = new ApUserSearch();apUserSearch.setUserId(userId);apUserSearch.setKeyword(keyword);apUserSearch.setCreatedTime(new Date());Query query1 = Query.query(Criteria.where("userId").is(userId));query1.with(Sort.by(Sort.Direction.DESC, "createTime"));List<ApUserSearch> apUserSearchList = mongoTemplate.find(query1, ApUserSearch.class);if(apUserSearchList == null || apUserSearchList.size() < 10){mongoTemplate.save(apUserSearch);}else{ApUserSearch lastUserSearch = apUserSearchList.get(apUserSearchList.size() - 1);mongoTemplate.findAndReplace(Query.query(Criteria.where("id").is(lastUserSearch.getId())), apUserSearch);}}
}

在文章搜索中调用, 因为未登录也可能有token(游客), 所以需要判断是否登录.

ApUser user = AppThreadLocalUtil.getUser();
// 异步调用, 保存搜索记录
if(user!=null && dto.getFromIndex() == 0){apUserSearchService.insert(dto.getSearchWords(), user.getId());
}

查询搜索历史

public ResponseResult findUserSearch() {// 获取当前用户ApUser user = AppThreadLocalUtil.getUser();if(user == null){return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);}// 根据用户查询数据, 根据时间排序Query query = Query.query(Criteria.where("userId").is(user.getId()));query.with(Sort.by(Sort.Direction.DESC, "createdTime"));List<ApUserSearch> apUserSearchList = mongoTemplate.find(query, ApUserSearch.class);return ResponseResult.okResult(apUserSearchList);
}

删除搜索历史

public ResponseResult delUserSearch(HistorySearchDto dto) {// 检查参数if(dto.getId() == null){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}// 获取当前用户ApUser user = AppThreadLocalUtil.getUser();if(user == null){return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);}// 删除Query query = Query.query(Criteria.where("id").is(dto.getId()).and("userId").is(user.getId()));mongoTemplate.remove(query, ApUserSearch.class);return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);
}

搜索联想词

public class ApAssociateWordsServiceImpl implements ApAssociateWordsService {@Autowiredprivate MongoTemplate mongoTemplate;/*** 搜索联想词* @param dto* @return*/@Overridepublic ResponseResult search(UserSearchDto dto) {// 1. 检查参数if(StringUtils.isBlank(dto.getSearchWords())){return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}// 2. 分页检索if(dto.getPageSize() > 20){dto.setPageSize(20);}// 3. 执行查询, 模糊查询Query query = Query.query(Criteria.where("associateWords").regex(".*?\\" + dto.getSearchWords() + ".*"));query.limit(dto.getPageSize());List<ApAssociateWords> apAssociateWordsList = mongoTemplate.find(query, ApAssociateWords.class);return ResponseResult.okResult(apAssociateWordsList);}
}

来源

黑马程序员. 黑马头条

Gitee

https://gitee.com/yu-ba-ba-ba/leadnews

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/51550.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

时序分解 | MATLAB实现基于SGMD辛几何模态分解的信号分解分量可视化

时序分解 | MATLAB实现基于SGMD辛几何模态分解的信号分解分量可视化 目录 时序分解 | MATLAB实现基于SGMD辛几何模态分解的信号分解分量可视化效果一览基本介绍程序设计参考资料 效果一览 基本介绍 SGMD分解算法&#xff08;辛几何模态分解&#xff09;&#xff0c;分解结果可视…

再学http-为什么文件上传要转成Base64?

1 前言 最近在开发中遇到文件上传采用Base64的方式上传&#xff0c;记得以前刚开始学http上传文件的时候&#xff0c;都是通过content-type为multipart/form-data方式直接上传二进制文件&#xff0c;我们知道都通过网络传输最终只能传输二进制流&#xff0c;所以毫无疑问他们本…

超越界限:大模型应用领域扩展,探索文本分类、文本匹配、信息抽取和性格测试等多领域应用

超越界限&#xff1a;大模型应用领域扩展&#xff0c;探索文本分类、文本匹配、信息抽取和性格测试等多领域应用 随着 ChatGPT 和 GPT-4 等强大生成模型出现&#xff0c;自然语言处理任务方式正在逐步发生改变。鉴于大模型强大的任务处理能力&#xff0c;未来我们或将不再为每…

33、在SpringBoot项目添加Web组件(Servlet、Filter 和 Listener) 的三种方法

通过Spring Bean 来添加 Servlet、Filter 和 Listener ★ 添加Web组件&#xff08;Servlet、Filter、Listener&#xff09;的三种方式&#xff1a; - 使用Spring Bean添加Servlet、Filter或Listener。- 使用XxxRegistrationBean手动添加Servlet、Filter或Listener。- 使用Clas…

QT6安装完成后,再安装低版本的MinGW或其他组件方式

首先进入点击安装的uinstall Qt 并不是真的卸载 通过下面几步 1&#xff0c;首先登录自己账户 2&#xff0c;然后进入欢迎中&#xff0c;点击“添加和移除组件” 3&#xff0c;然后检索自己需要的安装内容

Unity实现广告滚动播放、循环播放、鼠标切换的效果

效果&#xff1a; 场景结构&#xff1a; 特殊物体&#xff1a;panel下面用排列组件horizent layout group放置多个需要显示的面板&#xff0c;用mask遮罩好。 using System.Collections; using System.Collections.Generic; using DG.Tweening; using UnityEngine; using Unity…

第4篇:vscode+platformio搭建esp32 arduino开发环境

第1篇:Arduino与ESP32开发板的安装方法 第2篇:ESP32 helloword第一个程序示范点亮板载LED 第3篇:vscode搭建esp32 arduino开发环境 1.配置默认安装路径&#xff0c;安装到D盘。 打开环境变量&#xff0c;点击新建 输入变量名PLATFORMIO_CORE_DIR与路径&#xff1a;D:\PLATF…

linux服务TCP参数配置

Linux TCP参数配置 阿里云规范 1.【推荐】高并发服务器建议调小 TCP 协议的 time_wait 超时时间。 说明&#xff1a;操作系统默认 240 秒后&#xff0c;才会关闭处于 time_wait 状态的连接&#xff0c;在高并发访问下&#xff0c;服务器端会因为处于 time_wait 的连接数太多&am…

idea切换Git分支时保存未提交的文件

解决方案 我们现在有三个分支&#xff0c;如下图&#xff1a; 我们目前在tenant分支上进行开发&#xff0c;需要去修复master的Bug&#xff0c;假设我们在tenant分支上修改了一个文件&#xff0c;如下图&#xff1a; 方法一&#xff1a;使用Shelve Changes 1、选中tenant上你不…

高性能服务器Nodejs操作Mysql数据库

目录 1 Node 操作 mysql1.2 操作 mysql 数据库 2 Web 开发模式2.1 服务端渲染2.2 前后端分离2.3 如何选择 3 身份认证3.1 Session 认证机制3.2 JWT 认证机制 1 Node 操作 mysql 数据库和身份认证 配置 mysql 模块 安装 mysql 模块 npm install mysql建立连接 const mysql …

Android相机-HAL-Rockchip-hal3

引言&#xff1a; 对于Android相机的 HAL层而言对上实现一套Framework的API接口&#xff0c;对下通过V4L2框架实现与kernel的交互。不同的平台会有不同的实现方案。主要是对Android HAL3的接口的实现。看看rockchip是怎么支持hal3的&#xff1f; 代码目录&#xff1a; hardw…

python+tkinter实现多页面多菜单的demo实例

本篇文章主要讲解,python+tkinter多页面多菜单的demo实例,支持一个新窗口弹出、多页面切换,顶部菜单构建及事件绑定。 日期:2023年8月25日 版本:python3.9.6 实际效果 消息菜单-具体效果: 页面菜单具体效果: 事件菜单具体效果: 环境及依赖 python 3.9.6 依赖信息: …

rabbitMq安装后无法启动可视化页面http://localhost:15672处理

本次安装环境信息&#xff1a; 系统&#xff1a;win10 64位专业版 erlang&#xff1a;otp_win64_23.0 rabbitMQ&#xff1a;rabbitmq-server-3.8.5 安装rabbitMQ需要依赖erlang语言环境&#xff0c;所以需要我们下载erlang的环境安装程序。 一、下载安装程序 rabbitMQ安装…

java八股文面试[java基础]——接口和抽象类的区别

知识来源&#xff1a; 【基础】接口和抽象类_哔哩哔哩_bilibili 【2023年面试】Java中抽象类和接口有什么区别_哔哩哔哩_bilibili 【23版面试突击】抽象类和接口的区别&#xff0c;类可以继承多个类么&#xff0c;接口可以继承多个接口么,类可以实现多个接口么&#xff1f;_…

上门服务系统|上门服务小程序如何提升生活质量?

上门服务其实就是本地生活服务的升级&#xff0c;上门服务包含很多行业可以做的。例如&#xff1a;厨师上门、上门家电维修、跑腿等等。如今各类本地化生活服务越来越受大家的喜爱。基于此市场愿景&#xff0c;我们来谈谈上门服务系统功能。 一、上门服务系统功能 1、预约服务…

API 网关基础

目录 一、网关概述二、网关提供的功能三、常见网关系统3.1 Netflix Zuul3.2 Spring Cloud Gateway3.3 Kong3.4 APISIX3.5 Shenyu 一、网关概述 API网关是一个服务器&#xff0c;是系统的唯一入口。 从面向对象设计的角度看&#xff0c;它与外观模式类似。API网关封装了系统内部…

【SpringCloud技术专题】「Gateway网关系列」(1)微服务网关服务的Gateway组件的原理介绍分析

为什么要有服务网关? 我们都知道在微服务架构中&#xff0c;系统会被拆分为很多个微服务。那么作为客户端要如何去调用这么多的微服务呢&#xff1f;难道要一个个的去调用吗&#xff1f;很显然这是不太实际的&#xff0c;我们需要有一个统一的接口与这些微服务打交道&#xf…

Streamlit 讲解专栏(十):数据可视化-图表绘制详解(上)

文章目录 1 前言2 st.line_chart&#xff1a;绘制线状图3 st.area_chart&#xff1a;绘制面积图4 st.bar_chart&#xff1a;绘制柱状图5 st.pyplot&#xff1a;绘制自定义图表6 结语 1 前言 在数据可视化的世界中&#xff0c;绘制清晰、易于理解的图表是非常关键的。Streamlit…

HCIP-OpenStack组件之neutron

neutron&#xff08;ovs、ovn&#xff09; OVS OVS(Open vSwitch)是虚拟交换机&#xff0c;遵循SDN(Software Defined Network&#xff0c;软件定义网络)架构来管理的。 OVS介绍参考&#xff1a;https://mp.weixin.qq.com/s?__bizMzAwMDQyOTcwOA&mid2247485088&idx1…

【WebSocket】前端使用WebSocket实时通信

目录 前言什么是WebSocketWebSocket的工作原理WebSocket与HTTP的关系HTTP建立持久化连接WebSocket类封装 前言 最近写项目&#xff0c;需要实现消息通知和实时聊天的功能&#xff0c;就去了解了一些关于websocket的知识&#xff0c;总结如下。 什么是WebSocket WebSocket 是一…