JavaWeb_LeadNews_Day7-ElasticSearch, Mongodb

这篇具有很好参考价值的文章主要介绍了JavaWeb_LeadNews_Day7-ElasticSearch, Mongodb。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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文章搜索

思路分析

JavaWeb_LeadNews_Day7-ElasticSearch, Mongodb,JavaWeb开发,# JavaWeb开发-LeadNews,elasticsearch,mongodb,java,spring cloud,spring boot,后端,分布式

具体实现

  • 配置
    没有使用数据库, 所以无需数据源的自动配置
    spring:
        autoconfigure:
            exclude: org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
    elasticsearch:
        host: 192.168.174.133
        port: 9200
    
  • 业务代码
    @Service
    public class ArticleSearchServiceImpl implements ArticleSearchService {
    
        @Autowired
        private RestHighLevelClient restHighLevelClient;
    
        /**
         * es文章分页检索
         * @param dto
         * @return
         */
        @Override
        public 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 设置高亮 title
            HighlightBuilder 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-search
        uri: lb://leadnews-search
        predicates:
            - Path=/search/**
        filters:
            - StripPrefix= 1
    

新增文章创建索引

思路分析

JavaWeb_LeadNews_Day7-ElasticSearch, Mongodb,JavaWeb开发,# JavaWeb开发-LeadNews,elasticsearch,mongodb,java,spring cloud,spring boot,后端,分布式

具体实现

  • Producer
    SearchArticleVo需要静态地址, 所以需要在FreeMarker生成静态文章, 上传到MinIo之后再发送创建索引的消息
    @Service
    @Slf4j
    @Transactional
    public class ArticleFreemarkerServiceImpl implements ArticleFreemarkerService {
    
        ...
        @Override
        @Async
        public void buildArticleToMinIO(ApArticle article, String content) {
            if(StringUtils.isNotBlank(content)) {
                ...
    
                // kafka: 新增文章创建索引, 发送消息
                createArticleESIndex(article, content, path);
            }
        }
    
        @Autowired
        private 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 {
    
        @Autowired
        private 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.133
                port: 27017
                database: leadnews-history
    
  • 使用
    public class MongoTest {
    
    
        @Autowired
        private MongoTemplate mongoTemplate;
    
        //保存
        @Test
        public void saveTest(){
            ApAssociateWords apAssociateWords = new ApAssociateWords();
            apAssociateWords.setAssociateWords("黑马头条");
            apAssociateWords.setCreatedTime(new Date());
            mongoTemplate.save(apAssociateWords);
        }
    
        //查询一个
        @Test
        public void saveFindOne(){
            ApAssociateWords apAssociateWords = mongoTemplate.findById("64e46fd4f3a760442bf50527", ApAssociateWords.class);
            System.out.println(apAssociateWords);
        }
    
        //条件查询
        @Test
        public 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);
        }
    
        @Test
        public void testDel(){
            mongoTemplate.remove(Query.query(Criteria.where("associateWords").is("黑马头条")),ApAssociateWords.class);
        }
    }
    

app文章搜索记录

保存搜索记录

思路分析

异步保存
JavaWeb_LeadNews_Day7-ElasticSearch, Mongodb,JavaWeb开发,# JavaWeb开发-LeadNews,elasticsearch,mongodb,java,spring cloud,spring boot,后端,分布式
保存数据
JavaWeb_LeadNews_Day7-ElasticSearch, Mongodb,JavaWeb开发,# JavaWeb开发-LeadNews,elasticsearch,mongodb,java,spring cloud,spring boot,后端,分布式

具体实现

public class ApUserSearchServiceImpl implements ApUserSearchService {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 保存用户搜索记录
     * @param keyword
     * @param userId
     */
    @Override
    @Async
    public 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. 不存在, 判断当前历史记录总数量是否超过10
        apUserSearch = 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 {

    @Autowired
    private MongoTemplate mongoTemplate;

    /**
     * 搜索联想词
     * @param dto
     * @return
     */
    @Override
    public 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文章来源地址https://www.toymoban.com/news/detail-670750.html

到了这里,关于JavaWeb_LeadNews_Day7-ElasticSearch, Mongodb的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • JavaWeb_LeadNews_Day4-阿里云内容安全, 雪花算法, app文章保存, 自媒体文章审核

    依赖 实现 总结 工具类太复杂, 云盾内容安全也没开通(要企业认证), 看看测试好了 测试图片审核会报错, 可能是没开通 背景 技术选型 方案 优势 劣势 redis (INCR)生成一个全局连续递增的数字类型主键 增加了一个外部组件的依赖, Redis不可以, 则整个数据库将无法再插入 UUID 全局

    2024年02月15日
    浏览(42)
  • JavaWeb学习-Day10

    准备工作    开发流程:  开发接口步骤:  删除部门:  新增部门:    简化代码: limit:分页展示,公式:(页数-1)*页面总数,页面总数   目前出现的问题: 1.网页没有图形化界面,只有从数据库读取的信息,postman可以 正常运行,初步怀疑是前端和后端Java代码没有连

    2024年02月11日
    浏览(33)
  • 【JavaWeb】day01-HTML&CSS

    图片标签: img src :指定图像URL(绝对路径/相对路径) width :图像宽度(像素/相对于父元素的百分比) height :图像高度(像素/相对于父元素的百分比) 标题标签: h1 - h6 水平线标签: hr 超链接: a href :指定资源访问的url target :指定在何处打开资源链接 _self :默认值,

    2024年02月04日
    浏览(34)
  • 【javaweb】学习日记Day4 - Maven 依赖管理 Web入门

    目录 一、Maven入门 - 管理和构建java项目的工具 1、IDEA如何构建Maven项目 2、Maven 坐标 (1)定义 (2)主要组成 3、IDEA如何导入和删除项目 二、Maven - 依赖管理 1、依赖配置 2、依赖传递 (1)查看依赖  (2)排除依赖 3、依赖范围 三、Web 入门 1、Springboot web入门体验 2、HTTP简述

    2024年02月11日
    浏览(53)
  • 【javaweb】学习日记Day3 - Ajax 前后端分离开发 入门

    目录 一、Ajax 1、简介 2、Axios (没懂 暂留) (1)请求方式别名 (2)发送get请求 (3)发送post请求 (4)案例 二、前端工程化 1、Vue项目-目录结构 2、Vue项目-启动 (1)vscode页面启动 (2)cmd命令框启动 3、配置Vue端口号 4、Vue项目开发流程 三、Vue组件库 - Element  1、快速入门

    2024年02月12日
    浏览(37)
  • JavaWeb_瑞吉外卖_项目优化Day10-Spring Cache

    提交步骤: 生成空仓库, 不要加任何文件 右键项目, add整个项目 commit和push, push时添加远程仓库地址 新建分支步骤: 在本地新建一个分支 push 注入redis对象 将验证码保存到redis, 有效期5分钟 获取验证码, 登录成功后删除验证码 获取缓存数据 删除缓存数据 Spring Cache是一个框架,

    2024年02月13日
    浏览(44)
  • Java学习day3——Javaweb登录页面设计(1)(含JSP代码)

    本文主要的内容是完成网页登录页面设计,以及判断用户名密码是否正确,如果正确,进入下一页面,并输出sessionID,若错误,则在登录页面给出用户名或密码错误提示,并在登录页面显示访问次数。 登录页面(userLogin.jsp) 用户名输入框 密码输入框 提交内容到登录处理页面

    2023年04月18日
    浏览(84)
  • JavaWeb_瑞吉外卖_业务开发Day5-套餐管理, 短信发送, 手机验证码登录

    总结 接收List数据时, 需要加上 @RequestParam 注解 操作2个及2个以上表, 加上 @Transactional 事务注解, 保持数据的一致性. 发送短信 生成验证码 黑马程序员. 瑞吉外卖项目

    2024年02月12日
    浏览(37)
  • JavaWeb_SpringCloud微服务_Day4-MQ, RabbitMQ, SpringAMQP

    优点: 时效性强, 可以立即得到结果 缺点: 耦合度高 性能和吞吐能力下降 有额外的资源消耗 有级联失败问题 优点: 耦合度低 吞吐量提升 故障隔离 流量削峰 缺点: 依赖于Broker的可靠性, 安全性, 吞吐能力 架构复杂, 业务没有明显的流程线, 不好追踪管理 RabbitMq ActiveMQ RocketMQ K

    2024年02月16日
    浏览(46)
  • JavaWeb_SpringCloud微服务_Day1-eureka, ribbon, nacos

    Dubbo SpringCloud SpringCloudAlibaba 注册中心 zookeeper, Redis Eureka, Consul Nacos, Eureka 服务远程调用 Dubbo协议 Feign(http协议) Dubbo, Feign 配置中心 无 SpringCloudConfig SpringCloudConfig, Nacos 服务网关 无 SpringCloudGateway, Zuul SpringCloudGateway, Zuul 服务监控和保护 dubbo-admin, 功能弱 Hystrix Sentinel 注册RestTem

    2024年02月16日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包