文档总结与关键代码解析
1. ElasticSearch环境搭建
- 核心目标:构建支持中文分词的高效搜索环境。
- 关键步骤:
- Docker部署:使用
elasticsearch:7.4.0
镜像创建容器,配置单节点模式。 - IK分词器:将
elasticsearch-analysis-ik-7.4.0.zip
解压至插件目录,支持中文分词。 - 索引与映射:通过Postman创建索引
app_info_article
,定义字段类型(如text
使用ik_smart
分词)。
- Docker部署:使用
# 创建ElasticSearch容器
docker run -id --name elasticsearch -p 9200:9200 -p 9300:9300 \-v /plugins:/usr/share/elasticsearch/plugins \-e "discovery.type=single-node" elasticsearch:7.4.0
2. 文章搜索功能实现
- 核心逻辑:用户输入关键词,通过ElasticSearch实现多条件复合查询,返回高亮结果。
- 关键代码:
- 查询条件构建:使用
BoolQueryBuilder
组合关键字查询和时间范围过滤。 - 高亮配置:通过
HighlightBuilder
设置高亮字段和样式。 - 结果处理:解析命中结果,合并高亮标题与原始数据。
- 查询条件构建:使用
// 构建布尔查询
BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
boolQuery.must(QueryBuilders.queryStringQuery(keyword).field("title").field("content"));
boolQuery.filter(QueryBuilders.rangeQuery("publishTime").lt(minTime));// 设置高亮
HighlightBuilder highlightBuilder = new HighlightBuilder().field("title").preTags("<font style='color: red;'>").postTags("</font>");
searchSourceBuilder.highlighter(highlightBuilder);
3. 搜索历史记录
- 数据存储:使用MongoDB存储用户搜索记录,每个用户最多保留10条按时间倒序的记录。
- 关键操作:
- 异步保存:通过
@Async
注解异步调用保存方法,避免阻塞主线程。 - 历史清理:超过10条时替换最旧的记录。
- 异步保存:通过
// 异步保存搜索记录
@Async
public void insert(String keyword, Integer userId) {// 查询是否存在相同关键词Query query = Query.query(Criteria.where("userId").is(userId).and("keyword").is(keyword));ApUserSearch existRecord = mongoTemplate.findOne(query, ApUserSearch.class);// 不存在时检查数量并插入/替换if (existRecord == null) {List<ApUserSearch> records = mongoTemplate.find(Query.query(Criteria.where("userId").is(userId)), ApUserSearch.class);if (records.size() >= 10) {// 删除最旧记录mongoTemplate.remove(records.get(records.size() - 1));}mongoTemplate.save(new ApUserSearch(userId, keyword, new Date()));}
}
4. 联想词查询
- 数据来源:预存高频搜索词到MongoDB集合
ap_associate_words
。 - 查询逻辑:使用正则表达式实现模糊匹配,返回匹配的联想词列表。
// 模糊查询联想词
Query query = Query.query(Criteria.where("associateWords").regex(".*" + keyword + ".*"));
List<ApAssociateWords> words = mongoTemplate.find(query.limit(pageSize), ApAssociateWords.class);
5. 异步消息与索引同步
- 数据同步:文章审核通过后,通过Kafka发送消息,搜索服务消费消息并更新ElasticSearch索引。
- 关键代码:
- 生产者(文章服务):将文章数据序列化为JSON发送至Kafka Topic。
- 消费者(搜索服务):监听Topic,解析数据并写入ElasticSearch。
// 文章服务发送消息
kafkaTemplate.send(ArticleConstants.ARTICLE_ES_SYNC_TOPIC, JSON.toJSONString(articleVo));// 搜索服务消费消息
@KafkaListener(topics = ArticleConstants.ARTICLE_ES_SYNC_TOPIC)
public void onMessage(String message) {SearchArticleVo vo = JSON.parseObject(message, SearchArticleVo.class);IndexRequest request = new IndexRequest("app_info_article").id(vo.getId().toString());request.source(message, XContentType.JSON);restHighLevelClient.index(request, RequestOptions.DEFAULT);
}
关键总结
-
技术选型:
- ElasticSearch:支持高性能全文检索,适合复杂查询和高亮需求。
- MongoDB:灵活存储用户行为数据(如搜索历史),支持快速CRUD。
- Kafka:实现服务间异步通信,保证数据最终一致性。
-
核心功能亮点:
- 高亮显示:通过ElasticSearch的高亮API动态标记关键词。
- 历史记录管理:基于MongoDB的异步写入和自动清理机制。
- 联想词优化:正则模糊匹配提升搜索建议的灵活性。
-
配置要点:
- Nacos配置:统一管理ElasticSearch和Kafka连接信息。
- 依赖注入:确保
RestHighLevelClient
和MongoTemplate
正确初始化。
通过以上设计,系统实现了高效搜索、用户行为记录和智能联想功能,满足App端对搜索体验的核心需求。