Elasticsearch高效文章搜索實踐

功能

image-20250610211130171

創建索引和映射

image-20250610213446050

使用postman添加映射和查詢

image-20250610213733416

查詢所有的文章信息,批量導入到es索引庫中

image-20250610214358841
server:port: 9999
spring:application:name: es-articledatasource:driver-class-name: com.mysql.jdbc.Driverurl: jdbc:mysql://localhost:3306/leadnews_article?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTCusername: rootpassword: root
# 設置Mapper接口所對應的XML文件位置,如果你在Mapper接口中有自定義方法,需要進行該配置
mybatis-plus:mapper-locations: classpath*:mapper/*.xml# 設置別名包掃描路徑,通過該屬性可以給包中的類注冊別名type-aliases-package: com.heima.model.article.pojos#自定義elasticsearch連接配置
elasticsearch:host: 192.168.200.130port: 9200

導入到es索引庫

/*** 注意:數據量的導入,如果數據量過大,需要分頁導入** @throws Exception*/
@Test
public void init() throws Exception {// 查詢所有符合條件的文章數據List<SearchArticleVo> searchArticleVos = apArticleMapper.loadArticleList();// 批量導入到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);
}

需求說明

image-20250610221421008

搜索接口定義

image-20250610222047807

UserSearchDto

image-20250610222355123

實現步驟

image-20250612193842072

image-20250612193949445

image-20250612194110538

文章搜索服務實現

/*** 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);}ApUser user = AppThreadLocalUtil.getUser();//異步調用 保存搜索記錄if(user != null && dto.getFromIndex() == 0){apUserSearchService.insert(dto.getSearchWords(), user.getId());}//2.設置查詢條件SearchRequest searchRequest = new SearchRequest("app_info_article");SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();//布爾查詢BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();//關鍵字的分詞之后查詢QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(dto.getSearchWords()).field("title").field("content").defaultOperator(Operator.OR);boolQueryBuilder.must(queryStringQueryBuilder);//查詢小于mindate的數據RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("publishTime").lt(dto.getMinBehotTime().getTime());boolQueryBuilder.filter(rangeQueryBuilder);//分頁查詢searchSourceBuilder.from(0);searchSourceBuilder.size(dto.getPageSize());//按照發布時間倒序查詢searchSourceBuilder.sort("publishTime", SortOrder.DESC);//設置高亮  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);}

新增文章同步添加索引

/*** 創建文章索引** @param apArticle* @param content* @param path*/
private void createArticleEsIndex(ApArticle apArticle, String content, String path) {SearchArticleVo vo = new SearchArticleVo();BeanUtils.copyProperties(apArticle, vo);vo.setContent(content);vo.setStaticUrl(path);kafkaTemplate.send(ArticleConstants.ARTICLE_ES_SYNC_TOPIC, JSON.toJSONString(vo));
}

同步文章數據

@Component
@Slf4j
public class SyncArticleListener {@Autowiredprivate RestHighLevelClient  restHighLevelClient;/*** 同步文章數據* @param message*/@KafkaListener(topics = ArticleConstants.ARTICLE_ES_SYNC_TOPIC)public void onMessage(String message) {if (StringUtils.isNotBlank(message)) {SearchArticleVo searchArticleVo = JSON.parseObject(message, SearchArticleVo.class);IndexRequest indexRequest = new IndexRequest("app_info_article");indexRequest.id(searchArticleVo.getId().toString());indexRequest.source(message, XContentType.JSON);try {restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);} catch (IOException e) {log.error("sync es error = {}", e.getMessage(), e);}}}
}

搜索記錄

需求說明

image-20250613221520518

數據存儲說明

image-20250613221753764

保存搜索記錄-實現思路

image-20250613230006106

image-20250613230334610

image-20250613230414766

image-20250613230621594

用戶搜索服務實現

保存用戶搜索歷史記錄

/*** 保存用戶搜索歷史記錄** @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, "createdTime"));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);}}

查詢用戶搜索歷史記錄

/*** 查詢用戶搜索歷史記錄* @return*/@Overridepublic ResponseResult findUserSearch() {// 獲取當前用戶ApUser user = AppThreadLocalUtil.getUser();if (user == null) {return ResponseResult.errorResult(AppHttpCodeEnum.NEED_LOGIN);}// 根據當前用戶查詢數據,按照時間倒序List<ApUserSearch> apUserSearches = mongoTemplate.find(Query.query(Criteria.where("userId").is(user.getId())).with(Sort.by(Sort.Direction.DESC, "createdTime")), ApUserSearch.class);return ResponseResult.okResult(apUserSearches);}

刪除用戶搜索歷史記錄

/*** 刪除用戶搜索歷史記錄* @param dto* @return*/@Overridepublic 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);}// 刪除mongoTemplate.remove(Query.query(Criteria.where("userId").is(user.getId()).and("id").is(dto.getId())), ApUserSearch.class);return ResponseResult.okResult(AppHttpCodeEnum.SUCCESS);}

image-20250614173542679

image-20250614173634456

關鍵字聯想詞服務實現

image-20250614175924606

image-20250614180314561

image-20250614180446769

聯想詞查詢

/*** 聯想詞查詢* @param dto* @return*/@Override
public ResponseResult search(UserSearchDto dto) {// 檢查參數if (StringUtils.isBlank(dto.getSearchWords())) {return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);}// 分頁檢查if (dto.getPageSize() > 20) {dto.setPageSize(20);}// 執行查詢,模糊查詢Query query = Query.query(Criteria.where("associateWords").regex(".*?\\" + dto.getSearchWords() + ".*"));query.limit(dto.getPageSize());List<ApAssociateWords> apAssociateWords = mongoTemplate.find(query, ApAssociateWords.class);return ResponseResult.okResult(apAssociateWords);
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/84955.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/84955.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/84955.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

React 中除了react-router還有哪些路由方案

在用React開發時&#xff0c;常用的路由是react-router &#xff0c;但除此之外&#xff0c;還有兩個路由方案&#xff0c;因為他們具備 react-router 沒有的特性。 1. tanstack/router 1.1. 主要特性 100% 推斷的 TypeScript 支持 類型安全的導航 嵌套路由和布局路由 內置…

VINS-Fusion 簡介、安裝、編譯、數據集/相機實測

目錄 VINS-Fusion 簡介 安裝 VINS-Fusion 源碼安裝 運行數據集 雙目模式 單目IMU 模式 雙目IMU 模式 D455 相機實際運行 雙目IMU 模式 VINS-Fusion 簡介 VINS-Fusion 是繼 VINS-Mono 和 VINS-Mobile&#xff08;單目視覺慣導 SLAM 方案&#xff09;后&#xff0c;香港科 技大學…

SQL Developer 表復制

SQL Developer 表復制 此方法在數據量比較大時&#xff0c;比一條一條的insert要快得多&#xff1b;具體是會覆蓋掉原數據&#xff0c;還是增量的處理&#xff0c;請自行創建demo表測試一下。 注意&#xff1a;原庫版本要與目標庫數據庫版本一致&#xff0c;否則可能會報錯的。…

影視劇學經典系列-梁祝-《呂氏春秋·應同》

1、背景 07版電視劇《梁山伯與祝英臺》中&#xff0c;謝道韞作為先生&#xff0c;給學生講了其中的句子。 2、名言 君為尊&#xff0c;以白為黑&#xff0c;臣不能從&#xff1b;父雖親&#xff0c;以黑為白&#xff0c;子不能從”出自《呂氏春秋應同》 其意為&#xff0c;…

異步爬蟲---

代碼結構分析 這是一個同步新聞爬蟲程序&#xff0c;主要包含以下幾個部分&#xff1a; 們把爬蟲設計為一個類&#xff0c;類在初始化時&#xff0c;連接數據庫&#xff0c;初始化logger&#xff0c;創建網址池&#xff0c;加載hubs并設置到網址池。 爬蟲開始運行的入口就是r…

微服務架構中的 Kafka:異步通信與服務解耦(二)

三、Kafka 基礎入門 3.1 Kafka 是什么 Kafka 最初由 LinkedIn 公司開發&#xff0c;是一個開源的分布式事件流平臺&#xff0c;后成為 Apache 基金會的頂級項目 。它不僅僅是一個簡單的消息隊列&#xff0c;更是一個分布式流處理平臺&#xff0c;具備強大的消息隊列、存儲系統…

Lighthouse與首屏優化

之前提到首屏優化&#xff0c;想到的就是Vue項目首頁打開很慢需要優化。一般都是肉眼看看&#xff0c;對當前的加載速度并沒有一個準確的衡量標準&#xff0c;也沒有很清晰的解決思路。 前兩天我想給自己的網站申請谷歌廣告&#xff0c;聽說審核對網站的性能要求很高。于是網上…

Maven 之 打包項目時沒有使用本地倉庫依賴問題

背景 pom 中使用了第三方jar包&#xff0c;遠程倉庫設置的是阿里云&#xff0c;之前運行很好&#xff0c;今天不知道怎么的&#xff0c;打包總是報錯&#xff0c;阿里云倉庫無法找到依賴包(本來也沒有)&#xff0c;按理來說&#xff0c;編譯打包時會優先選擇本地倉庫的包才對&a…

Mysql基礎入門\期末速成

DDL 操作數據庫語句 創建&刪除數據庫語句 創建數據庫 create database 數據庫名稱; -- 直接創建 create database if not exists 數據庫名稱; -- 如果不存在&#xff0c;則創建 create database 數據庫名稱 default charset utf8mb4; -- 創建編譯類型utf8的數據類型 cre…

SCADA|KingSCADA4.0中歷史趨勢控件與之前版本的差異

哈嘍,你好啊,我是雷工! 最近用到KingSCADA4.0信創版本,也算嘗鮮使用。 在使用的過程中發現有些功能或多或少存在一些差異, 這里將遇到的一些不同總結一下,便于后期更好的使用。 01 歷史趨勢控件 在KingSCADA中有一個歷史趨勢曲線控件KSHTrend。 該控件既可以連接King…

ubuntu 拒絕ssh連接,連不上ssh,無法遠程登錄: Connection failed.

目錄 問題描述視窗 可視化桌面命令行 問題描述 [C:\~]$ Connecting to 192.166.8.85:22... Could not connect to 192.166.8.85 (port 22): Connection failed.Type help to learn how to use Xshell prompt. [C:\~]$ Connecting to 192.166.8.85:22... Could not connect to …

【大模型應用開發】向量數據庫向量檢索方法存在問題及優化

一、檢索結果重復 1. 問題分析 在構建向量數據庫時&#xff0c;對文檔分割會存在重復塊&#xff08;chunk_overlap&#xff1a;指兩個塊之間共享的字符數量&#xff0c;用于保持上下文的連貫性&#xff0c;避免分割丟失上下文信息&#xff09;&#xff0c;如下圖所示&#xf…

MySQL常用函數詳解之數值函數

MySQL常用函數詳解之數值函數 一、數值函數概述1.1 數值函數的作用1.2 數值函數分類 二、算術運算函數2.1 加法運算&#xff08;&#xff09;2.2 減法運算&#xff08;-&#xff09;2.3 乘法運算&#xff08;*&#xff09;2.4 除法運算&#xff08;/ 或 DIV&#xff09;2.5 取模…

13、Redis進階二之Redis數據安全性分析

? 、Redis性能壓測腳本介紹 Redis的所有數據是保存在內存當中的&#xff0c; 得益于內存?效的讀寫性能&#xff0c; Redis的性能是?常強悍的 。但 是&#xff0c;內存的缺點是斷電即丟失&#xff0c;所以 &#xff0c;在實際項?中&#xff0c; Redis—旦需要保存—些重要的…

【系統分析師】2011年真題:綜合知識-答案及詳解

文章目錄 【第1題】【第2~3題】【第4~5題】【第6題】【第7~8題】【第9題】【第10題】【第11題】【第12題】【第13題】【第14題】【第15題】【第16題】【第17題】【第18題】【第19~20題】【第21題】【第22題】【第23題】【第24~25題】【第26題】【第27題】【第28題】【第29題】【…

FastAPI-MCP構建自定義MCP工具實操指南

一、簡介 ? FastAPI-MCP是一個基于python FastAPI框架開發的開源項目&#xff0c;可以自動識別并暴露FastAPI接口為MCP工具 ? 擁有FastAPI框架的所有優點&#xff0c;如異步高并發、獨立遠程部署、OpenAPI文檔 ? 提供SSE、mcp-remote接入方式&#xff0c;支持設置授權訪問…

LLMs之Memory:《LLMs Do Not Have Human-Like Working Memory》翻譯與解讀

LLMs之Memory&#xff1a;《LLMs Do Not Have Human-Like Working Memory》翻譯與解讀 導讀&#xff1a;該論文通過三個精心設計的實驗&#xff0c;證明了當前的大型語言模型&#xff08;LLMs&#xff09;缺乏類似人類的工作記憶。實驗結果表明&#xff0c;LLMs無法在沒有明確外…

Node.js驗證碼:從生成到驗證的趣味之旅

文章目錄 Node.js驗證碼&#xff1a;從生成到驗證的趣味之旅&#x1f4dc; 引言&#xff1a;為什么需要驗證碼&#xff1f;1. 驗證碼的基本原理 &#x1f9e0;驗證碼工作流程示意圖 2. 技術棧準備 &#x1f6e0;?3. 驗證碼生成詳解 &#x1f3a8;3.1 生成SVG驗證碼3.2 轉換為P…

芯科科技攜最新Matter演示和參考應用精彩亮相Matter開放日和開發者大會

全面展示賦能Matter設備實現跨協議和跨海內外生態的技術能力 作為Matter標準創始廠商之一和其解決方案的領先供應商&#xff0c;Silicon Labs&#xff08;亦稱“芯科科技”&#xff09;于6月12至13日參加由連接標準聯盟中國成員組&#xff08;CMGC&#xff09;主辦的Matter年度…

AndroidStudio下載的SDK沒有tool目錄,或者想要使用uiautomatorviewer工具

1.如果沒有tool目錄可以使用下面的地址進行下載 https://dl.google.com/android/repository/tools_r25.2.5-windows.zip 2.并且把下載的文件解壓到放在AndroidStudio的目錄中 3.如果使用uiautomatorviewer.bat出現下面的錯誤 Unable to connect to adb.Check if adb is instal…