各大网站的软文怎么做,分销系统什么意思,阿里巴巴网站本土化建设,建手机端网站JavaWeb_LeadNews_Day7-ElasticSearch, Mongodb elasticsearch安装配置 app文章搜索创建索引库app文章搜索思路分析具体实现 新增文章创建索引思路分析具体实现 MongoDB安装配置SpringBoot集成MongoDB app文章搜索记录保存搜索记录思路分析具体实现 查询搜索历史删除搜索历史 搜… 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--
dependencygroupIdorg.elasticsearch.client/groupIdartifactIdelasticsearch-rest-high-level-client/artifactIdversion7.12.1/version
/dependency
dependencygroupIdorg.elasticsearch.client/groupIdartifactIdelasticsearch-rest-client/artifactIdversion7.12.1/version
/dependency
dependencygroupIdorg.elasticsearch/groupIdartifactIdelasticsearch/artifactIdversion7.12.1/version
/dependency导入数据Autowired
private ApArticleMapper apArticleMapper;Autowired
private RestHighLevelClient restHighLevelClient;/*** 注意数据量的导入如果数据量过大需要分页导入* throws Exception*/
Test
public void init() throws Exception {// 1. 查询所有符合条件的文章数据ListSearchArticleVo 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 stylecolor: red; font-size: inherit;);highlightBuilder.postTags(/font);searchSourceBuilder.highlighter(highlightBuilder);searchSourceBuilder.query(boolQueryBuilder);searchRequest.source(searchSourceBuilder);SearchResponse searchResponse restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);// 3. 结果封装返回ListMap 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 {...OverrideAsyncpublic void buildArticleToMinIO(ApArticle article, String content) {if(StringUtils.isNotBlank(content)) {...// kafka: 新增文章创建索引, 发送消息createArticleESIndex(article, content, path);}}Autowiredprivate KafkaTemplateString, 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));}
}ListenerComponent
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 mongoSpringBoot集成MongoDB
依赖dependencygroupIdorg.springframework.boot/groupIdartifactIdspring-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));ListApAssociateWords 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*/OverrideAsyncpublic 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));ListApUserSearch 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));ListApUserSearch 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());ListApAssociateWords apAssociateWordsList mongoTemplate.find(query, ApAssociateWords.class);return ResponseResult.okResult(apAssociateWordsList);}
}来源
黑马程序员. 黑马头条
Gitee
https://gitee.com/yu-ba-ba-ba/leadnews