当前位置: 首页 > news >正文

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.lryc.cn/news/138461.html

相关文章:

  • redux中间件理解,常见的中间件,实现原理。
  • 麒麟系统上安装 MySQL 8.0.24
  • vue 展开和收起
  • 限制立方样条(RCS)中的P for overall和P for nonlinear的计算
  • vue3+ts引入echarts并实现自动缩放
  • Compressor For Mac强大视频编辑工具 v4.6.5中文版
  • maven工程的目录结构
  • 5.1 webrtc线程模型
  • 【Linux网络】Cookie和session的关系
  • android 硬编码保存mp4
  • gitlab合并分支
  • 手撕 `np.transpose` : 三维数组的循环转置
  • 计算机竞赛 基于Django与深度学习的股票预测系统
  • CSS 小技能(一):HTML 两个图片竖着平铺、设置图片点击、设置滚动条颜色
  • 【论文阅读】CONAN:一种实用的、高精度、高效的APT实时检测系统(TDSC-2020)
  • P1328 [NOIP2014 提高组] 生活大爆炸版石头剪刀布
  • 基于Android水果蔬菜果蔬到家商城系统 微信小程序uniAPP的开发与实现
  • 【Python】从入门到上头—Python基础(2)
  • leetcode刷题之283:移动零
  • 【Spring Boot】SpringBoot和数据库交互: 使用Spring Data JPA
  • 自动化部署及监测平台基本架构
  • 基于NXP i.MX 6ULL核心板的物联网模块开发案例(1)
  • 【路由器】小米 WR30U 解锁并刷机
  • 数据库操作语句
  • Mr. Cappuccino的第64杯咖啡——Spring循环依赖问题
  • Adapting Language Models to Compress Contexts
  • Kubernetes(K8S)使用PV和PVC做存储安装mysql
  • Ansible Playbook 常用变量
  • 0103水平分片-jdbc-shardingsphere-中间件
  • Vue2.0+webpack 引入字体文件(eot,ttf,woff)