黑马头条-day10

文章目录

  • app端文章搜索
    • 1、文章搜索
      • 1.1 ElasticSearch环境搭建
      • 1.2 索引库创建
        • ①需求分析
        • ②ES导入数据场景分析
        • ③创建索引和映射
      • 1.3 索引数据同步
        • ①app文章历史数据导入ES
        • ②文章实时数据导入ES
      • 1.4 文章搜索多条件复合查询
        • ①关键词搜索
        • ②搜索接口定义
    • 2、搜索历史记录
      • 2.1 需求说明
      • 2.2 数据存储说明
      • 2.1 异步保存搜索历史
        • ①实现思路
      • 2.2 查看搜索历史列表
        • ①接口定义
      • 2.3 删除搜索历史
    • 3、联想词查询
      • 需求分析
      • 3.1 联想词的来源
      • 3.2 联想词功能实现
        • 接口定义
        • 正则表达式说明


app端文章搜索

1、文章搜索

1.1 ElasticSearch环境搭建

1、启动ElasticSearch

docker start elasticsearch

2、启动Kibana

docker start kibana

3、kibana测试分词效果

1.2 索引库创建

①需求分析

在这里插入图片描述

  • 用户输入关键词 比如java只要文章titile、content包含此关键词就可以搜索出来,搜索黑马程序员能把黑马、程序员相关都搜索出来
  • 搜索的文章结果里词条要高亮显示
  • 用户点击搜索结果任意一条可查看文章详情
②ES导入数据场景分析

在这里插入图片描述

③创建索引和映射

搜索结果页面展示什么内容?

  • 标题
  • 布局
  • 封面图片
  • 发布时间
  • 作者名称
  • 文章id
  • 作者id
  • 静态url

哪些字段需要索引和分词?

  • 标题
  • 内容

使用Kibana添加映射
索引库名称:app_info_article

PUT /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": "keyword"},"title":{"type":"text","analyzer":"ik_max_word"},"content":{"type":"text","analyzer":"ik_max_word"}}}
}

1.3 索引数据同步

①app文章历史数据导入ES

1、创建es索引和映射
前面创建过了
2、文章微服务集成es功能
导入es服务的依赖
3、编写单元测试将历史状态正常的文章数据同步到es中
数据量特别少一次导入
数据量特别多分批导入,一次一两千条

mapper接口和sql语句

/**
* 查询es需要的全部文章数据* @return*/
List<SearchArticleVo> loadSearchArticleList();
<select id="loadSearchArticleList" resultType="com.heima.model.search.vos.SearchArticleVo">select aa.*, aacc.content from ap_article aaleft join ap_article_config aac on aa.id=aac.article_idLEFT JOIN ap_article_content aacc on aa.id = aacc.article_id
where aac.is_down=0 and aac.is_delete=0</select>

测试类代码

@Autowired
private RestHighLevelClient client;
/*** 将历史文章数据导入ES中*/
@Test
public void testImportES() throws IOException {// 1. 查询所有状态正常的文章列表List<SearchArticleVo> searchArticleVoList = apArticleMapper.loadSearchArticleList();// 2. 构建BulkRequest批量请求对象BulkRequest bulkRequest = new BulkRequest();// 3. 遍历文章列表逐一添加IndexRequestfor (SearchArticleVo searchArticleVo : searchArticleVoList) {IndexRequest indexRequest = new IndexRequest("app_info_article");indexRequest.source(JSON.toJSONString(searchArticleVo), XContentType.JSON).id(String.valueOf(searchArticleVo.getId()));bulkRequest.add(indexRequest);}// 4. 执行restHighLevelClient的bulk批量插入文档请求BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);// 5. 获取响应结果数据并输出int status = bulk.status().getStatus();System.out.println("导入完成,响应状态码"+status);System.out.println("==============================================================================================");BulkItemResponse[] items = bulk.getItems();for (BulkItemResponse item : items) {String result = item.getResponse().getResult().getLowercase();System.out.println(result);}
}
②文章实时数据导入ES

跨服务调用的异步,要使用mq
在这里插入图片描述
生产者

kafka:bootstrap-servers: 192.168.200.130:9092producer:retries: 10key-serializer: org.apache.kafka.common.serialization.StringSerializervalue-serializer: org.apache.kafka.common.serialization.StringSerializer
// 5. 封装es所需的数据转为JSON,生产到Kafka中
SearchArticleVo searchArticleVo = new SearchArticleVo();
BeanUtils.copyProperties(apArticle,searchArticleVo);
searchArticleVo.setStaticUrl(url);
searchArticleVo.setContent(contentStr);
String articleJson = JSON.toJSONString(searchArticleVo);
kafkaTemplate.send(ArticleConstants.ARTICLE_ES_SYNC_TOPIC,articleJson);

消费者

spring:kafka:bootstrap-servers: 192.168.200.130:9092consumer:group-id: ${spring.application.name}key-deserializer: org.apache.kafka.common.serialization.StringDeserializervalue-deserializer: org.apache.kafka.common.serialization.StringDeserializer
@Component
@Slf4j
public class ApArticleImportESListener {@Autowiredprivate RestHighLevelClient client;@KafkaListener(topics = ArticleConstants.ARTICLE_ES_SYNC_TOPIC)public void msg (ConsumerRecord<String,String> consumerRecord) {if (consumerRecord != null) {String articleJSON = consumerRecord.value();SearchArticleVo searchArticleVo = JSON.parseObject(articleJSON, SearchArticleVo.class);IndexRequest indexRequest = new IndexRequest("app_info_article");indexRequest.source(articleJSON, XContentType.JSON).id(searchArticleVo.getId().toString());try {IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);String result = indexResponse.getResult().getLowercase();String desc = result.equals("created") ? "导入成功" : "导入失败";log.info("[异步导入APP文章到ES],导入结果:{}", desc);} catch (IOException e) {throw new RuntimeException(e);}}}
}

1.4 文章搜索多条件复合查询

①关键词搜索

在这里插入图片描述

②搜索接口定义

在这里插入图片描述

2、搜索历史记录

2.1 需求说明

在这里插入图片描述

  • 异步保存搜索记录
  • 默认查询10条搜索记录,按照搜索关键词的时间倒序
  • 可以删除搜索记录

2.2 数据存储说明

用户的搜索记录,需要给每一个用户都保存一份,数据量大,要求加载速度快,通常这样的数据存储到mongodb更合适,不建议直接存储到关系型数据库中

2.1 异步保存搜索历史

①实现思路

保存的数据量太大,不想同步影响效率,采用异步保存
在这里插入图片描述

@Service
@Slf4j
public class ApUserSearchServiceImpl implements ApUserSearchService {@Autowiredprivate MongoTemplate mongoTemplate;@Async("taskExecutor")@Overridepublic void insert(String keyword, Integer userId) {// 1. 查询搜索记录Query query = Query.query(Criteria.where("keyword").is(keyword).and("userId").is(userId));ApUserSearch apUserSearch = mongoTemplate.findOne(query, ApUserSearch.class);// 2. 如果搜索记录不存在,则保存搜索记录if (apUserSearch == null) {apUserSearch = new ApUserSearch();SnowflakeIdWorker isWorker = new SnowflakeIdWorker(10, 10);apUserSearch.setId(isWorker.nextId());// 使用雪花算法的值当做主键IDapUserSearch.setUserId(userId);apUserSearch.setKeyword(keyword);apUserSearch.setIsDeleted(0); // 未删除apUserSearch.setCreatedTime(new Date());apUserSearch.setUpdatedTime(new Date());mongoTemplate.save(apUserSearch);return;}// 3. 如果搜索记录存在且未删除,则更新updatedTimeif (apUserSearch.getIsDeleted() == 0) {apUserSearch.setUpdatedTime(new Date());mongoTemplate.save(apUserSearch);return;}// 4. 如果搜索记录存在且已删除,则更新为未删除及更新updateTimeapUserSearch.setIsDeleted(0);apUserSearch.setUpdatedTime(new Date());mongoTemplate.save(apUserSearch);}
}

2.2 查看搜索历史列表

①接口定义

按照当前用户,按照时间倒序查询
在这里插入图片描述

@Overridepublic ResponseResult findUserSearch() {// 根据条件查询搜索记录列表(条件:userId和isDeleted 结果:updateTime倒序)Query query = Query.query(Criteria.where("userId").is(ThreadLocalUtil.getUserId()).and("isDeleted").is(0)).with(Sort.by(Sort.Direction.DESC,"updateTime"));query.limit(10);List<ApUserSearch> apUserSearchList = mongoTemplate.find(query, ApUserSearch.class);return ResponseResult.okResult(apUserSearchList);}

2.3 删除搜索历史

根据搜索历史id删除
在这里插入图片描述

@Overridepublic ResponseResult delUserSearch(HistorySearchDto dto) {ApUserSearch apUserSearch = mongoTemplate.findById(dto.getId(), ApUserSearch.class);if (apUserSearch == null) {return ResponseResult.errorResult(AppHttpCodeEnum.DATA_NOT_EXIST,"搜索记录不存在");}// 更新记录为已删除apUserSearch.setIsDeleted(1);apUserSearch.setUpdatedTime(new Date());mongoTemplate.save(apUserSearch);return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);}

3、联想词查询

需求分析

根据用户输入的关键字展示联想词
在这里插入图片描述

3.1 联想词的来源

通常是网上搜索频率比较高的一些词,通常在企业中有两部分来源:
第一:自己维护搜索词
通过分析用户搜索频率较高的词,按照排名作为搜索词

第二:第三方获取
关键词规划师(百度)、5118、爱站网

3.2 联想词功能实现

接口定义

在这里插入图片描述

正则表达式说明

在这里插入图片描述

@Service
@Slf4j
public class ApAssociateWordsServiceImpl implements ApAssociateWordsService {@Autowiredprivate MongoTemplate mongoTemplate;@Overridepublic ResponseResult search(UserSearchDto dto) {// 替换一切特殊字符dto.setSearchWords(dto.getSearchWords().replaceAll("[^\u4e00-\u9fa5a-zA-z0-9]", ""));List<ApAssociateWords> apAssociateWordsList = mongoTemplate.find(Query.query(Criteria.where("associateWords").regex(".*?\\" + dto.getSearchWords() + ".*")).limit(dto.getPageSize()), ApAssociateWords.class);return ResponseResult.okResult(apAssociateWordsList);}
}

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

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

相关文章

积分商城管理系统的设计与实现

积分商城管理系统的设计与实现 获取源码——》公主号&#xff1a;计算机专业毕设大全

javascript给对象添加迭代器

迭代器是啥就自行百度了 为啥for…of可以遍历数组&#xff0c;为啥不能遍历对象&#xff0c;就是for…of会调用迭代器&#xff0c;而数组是内置了迭代器了&#xff0c;而对象没有内置&#xff0c;所以直接使用for…of遍历对象会报错&#xff0c;因此只用在对象的原型上面自定义…

YOLO算法改进Backbone系列之:EfficientViT

EfficientViT: Memory Effificient Vision Transformer with Cascaded Group Attention 摘要&#xff1a;视觉transformer由于其高模型能力而取得了巨大的成功。然而&#xff0c;它们卓越的性能伴随着沉重的计算成本&#xff0c;这使得它们不适合实时应用。在这篇论文中&#x…

一般情况下,硬件中使用Repeating Sequence出现波形很奇怪就是数据的周期频率和mcu运行的频率不一致导致的

一般情况下&#xff0c;出现波形很奇怪就是数据的周期频率和mcu运行的频率不一致导致的 把timer values 修改为0 1就好了&#xff0c;如果是0&#xff0c;0.1就不行&#xff0c;不会有下面的波形

YOLOv9中的“RepNCSPELAN4”结构!

RepNCSPELAN4结构出炉啦&#xff0c;收藏起来写论文用&#xff01; 1.代码&#xff1a; 代码路径&#xff1a;yolov9-main->models->common.py&#xff0c;代码如下&#xff1a; class RepNCSPELAN4(nn.Module):# csp-elandef __init__(self, c1, c2, c3, c4, c51): # …

使用EFCore连接SQLite

简介 在使用EFCore连接SQLite之前我们先来了解一下SQLite SQLite是一个轻量级、自包含、无服务器、零配置的事务性SQL数据库引擎&#xff0c;它支持SQL92标准的大多数查询语言并兼容ACID事务。具体如下&#xff1a; 轻量级&#xff1a;SQLite非常轻巧&#xff0c;它的库体积…

UE5 C++ Gas开发 学习记录(三)

添加AuraPlayerState,AuraAbilitySystemComponentBase和AuraAttributeSet 在Build.cs里添加 // Copyright Epic Games, Inc. All Rights Reserved. using UnrealBuildTool; public class MyGas : ModuleRules { public MyGas(ReadOnlyTargetRules Target) : base(Target) { P…

leetcode hot100打家劫舍三

本题是打家劫舍的变形&#xff0c;数据结构是树形。涉及到树的题目一定要想清楚树的遍历顺序&#xff08;前中后序&#xff09;。之后再考虑利用动态规划来解决。 动态规划是一直记录状态&#xff0c;我们可以根据动态规划的数组来记录变化的状态&#xff0c;最终求的自己想要…

Python字符串访问与拼接你搞懂了吗?

使用下标访问字符串&#xff0c;从0开始计数&#xff0c;-1表示最后一个字符。三种遍历字符串的方法&#xff1a;for循环、len()和enumerate()。字符串拼接只能是字符串之间使用&#xff0c;不能与数字拼接。 1.下标访问字符串 通过下标访问字符串的内容&#xff0c;下标从 0 …

Shell脚本介绍及脚本功能

文章目录 一、什么是shell二、hello word2.1 echo2.2第一个脚本 三、Bash的基本功能3.1别名3.2常用快捷键3.3输入输出3.4 输出重定向3.5 多命令执行3.6 管道符3.7 通配符和特殊符号 一、什么是shell Shell 是一个用 C 语言编写的程序&#xff0c;它是用户使用 Linux 的桥梁。S…

视频号视频下载教程:如何把微信视频号的视频下载下来

视频号下载相信不少人都多少有一些了解&#xff0c;但今天我们就来细说一下关于视频号视频下载的相关疑问&#xff0c;以及大家经常会问到底如何把微信视频号的视频下载下来&#xff1f; 视频号视频下载教程 视频号链接提取器详细使用指南&#xff0c;教你轻松下载号视频&…

Django后台管理(二)

一、自定义注册管理类介绍 官网:Django 管理站点 | Django 文档 | Django 注册模型除了使用 Django 默认的管理类admin,也可以自定义,比如: class StudentAdmin(admin.ModelAdmin):pass admin.site.register(Student, StudentAdmin)ModelAdmin 类是管理界面中模型的表示。…

功能富集分析 | GO| KEGG

写在前面 我们《复现SCI文章系列教程》专栏现在是免费开放&#xff0c;推出这个专栏差不多半年的时间&#xff0c;但是由于个人的精力和时间有限&#xff0c;只更新了一部分。后续的更新太慢了。因此&#xff0c;最终考虑后还是免费开放吧&#xff0c;反正不是什么那么神秘的东…

Linux环境下的性能分析 之 CPU篇(二)

2、CPU的使用情况分析 a、类似任务管理器的top & htop 说到对CPU的性能分析&#xff0c;大家一定不会忘记windows下那个最熟悉的工具&#xff1a;任务管理器。 有了这个玩意儿&#xff0c;我们就可以看到CPU的利用率&#xff0c;以及每一个进程所占用的CPU资源。那在Linu…

【论文精读】LLaMA1

摘要 以往的LLM&#xff08;Large Languages Models&#xff09;研究都遵从一个假设&#xff0c;即更多的参数将导致更好的性能。但也发现&#xff0c;给定计算预算限制后&#xff0c;最佳性能的模型不是参数最大的&#xff0c;而是数据更多的。对于实际场景&#xff0c;首选的…

Huggingface学习笔记

课程地址&#xff1a;【HuggingFace简明教程,BERT中文模型实战示例.NLP预训练模型,Transformers类库,datasets类库快速入门.】 什么是huggingface&#xff1f; huggingface是一个开源社区&#xff0c;提供了先进的NLP模型、数据集以及工具。 主要模型&#xff1a; 安装环境&…

【Java程序设计】【C00284】基于Springboot的校园疫情防控管理系统(有论文)

基于Springboot的校园疫情防控管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的校园疫情防控系统 本系统分为系统功能模块、管理员功能模块以及学生功能模块。 系统功能模块&#xff1a;在系统首页可以查…

LeetCode 1038.从二叉搜索树到更大和树

给定一个二叉搜索树 root (BST)&#xff0c;请将它的每个节点的值替换成树中大于或者等于该节点值的所有节点值之和。 提醒一下&#xff0c; 二叉搜索树 满足下列约束条件&#xff1a; 节点的左子树仅包含键 小于 节点键的节点。 节点的右子树仅包含键 大于 节点键的节点。 左…

Spring Cloud与Docker集成:微服务容器化解决方案详解

推荐一款AI网站 AI写作与AI绘画智能创作平台 - 海鲸AI | 智能AI助手&#xff0c;可以免费领取GPT3.5无限卡 Spring Cloud 和 Docker 是两个不同的技术&#xff0c;但它们可以一起工作以构建、部署和管理微服务架构。下面是它们各自的简介以及它们如何协同工作的原理解析。 Sp…

蜘蛛蜂优化算法SWO求解不闭合MD-MTSP,可以修改旅行商个数及起点(提供MATLAB代码)

1、蜘蛛蜂优化算法SWO 蜘蛛蜂优化算法&#xff08;Spider wasp optimizer&#xff0c;SWO&#xff09;由Mohamed Abdel-Basset等人于2023年提出&#xff0c;该算法模型雌性蜘蛛蜂的狩猎、筑巢和交配行为&#xff0c;具有搜索速度快&#xff0c;求解精度高的优势。VRPTW&#x…