赞
踩
1、启动ElasticSearch
docker start elasticsearch
2、启动Kibana
docker start kibana
3、kibana测试分词效果
java
只要文章titile、content包含此关键词就可以搜索出来,搜索黑马程序员
能把黑马、程序员
相关都搜索出来词条
要高亮显示搜索结果页面展示什么内容?
哪些字段需要索引和分词?
使用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、创建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 aa
left join ap_article_config aac on aa.id=aac.article_id
LEFT 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. 遍历文章列表逐一添加IndexRequest for (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); } }
跨服务调用的异步,要使用mq
生产者
kafka:
bootstrap-servers: 192.168.200.130:9092
producer:
retries: 10
key-serializer: org.apache.kafka.common.serialization.StringSerializer
value-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:9092
consumer:
group-id: ${spring.application.name}
key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
@Component @Slf4j public class ApArticleImportESListener { @Autowired private 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); } } } }
用户的搜索记录,需要给每一个用户都保存一份,数据量大,要求加载速度快,通常这样的数据存储到mongodb
更合适,不建议直接存储到关系型数据库中
保存的数据量太大,不想同步影响效率,采用异步保存
@Service @Slf4j public class ApUserSearchServiceImpl implements ApUserSearchService { @Autowired private MongoTemplate mongoTemplate; @Async("taskExecutor") @Override public 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());// 使用雪花算法的值当做主键ID apUserSearch.setUserId(userId); apUserSearch.setKeyword(keyword); apUserSearch.setIsDeleted(0); // 未删除 apUserSearch.setCreatedTime(new Date()); apUserSearch.setUpdatedTime(new Date()); mongoTemplate.save(apUserSearch); return; } // 3. 如果搜索记录存在且未删除,则更新updatedTime if (apUserSearch.getIsDeleted() == 0) { apUserSearch.setUpdatedTime(new Date()); mongoTemplate.save(apUserSearch); return; } // 4. 如果搜索记录存在且已删除,则更新为未删除及更新updateTime apUserSearch.setIsDeleted(0); apUserSearch.setUpdatedTime(new Date()); mongoTemplate.save(apUserSearch); } }
按照当前用户,按照时间倒序查询
@Override
public 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);
}
根据搜索历史id删除
@Override
public 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);
}
根据用户输入的关键字展示联想词
通常是网上搜索频率比较高的一些词,通常在企业中有两部分来源:
第一:自己维护搜索词
通过分析用户搜索频率较高的词,按照排名作为搜索词
第二:第三方获取
关键词规划师(百度)、5118、爱站网
@Service @Slf4j public class ApAssociateWordsServiceImpl implements ApAssociateWordsService { @Autowired private MongoTemplate mongoTemplate; @Override public 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); } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。