小程序也好,app也好,客户端还是什么乱七八糟也好,都会或多或少用到elastic search,作为一个使用海量数据的搜索引擎,吊打mysql
有小伙伴说了,我们mysql可以分库分表,还可以做集群,还可以主从复制,但是这里有个很严重的问题,多个数据库,当要获取一定范围的·1数据时,需要去多个数据库截取数据,再汇总,这无疑麻烦而且增加了多余的开销
这里的场景是,搜索文章,先要自定义个es索引名称,这里的索引名称就是指数据库中的表
,不管是建立索引也刚好,建立字段也好,都是通过es语句建立,类似于sql语句,至于es的安装和使用,我就不赘述了,只是说说该场景下es的使用
首先,建立索引
put请求 : http://192.168.200.130: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"
}
}
}
}
关于字段的一些详细内容,我后面可能会出相关说明,但是现在,小伙伴们了解下就可以了
然后是批量导入数据到es中,这里注意,这是一个测试类,你要在同等级的测试类中去运行
package com.heima.es;
import com.alibaba.fastjson.JSON;
import com.heima.es.mapper.ApArticleMapper;
import com.heima.es.pojo.SearchArticleVo;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.List;
@SpringBootTest
@RunWith(SpringRunner.class)
public class ApArticleTest {
@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);
}
}
接着就是完善查询数据,并作结果剖析
@Service
@Slf4j
@AllArgsConstructor
public class ArticleSearchServiceImpl implements ApArticleSearchService {
private RestHighLevelClient restHighLevelClient;
@Override
public ResponseResult search(UserSearchDto dto) throws IOException {
//3.结果封装返回
List<Map> list = new ArrayList<>();
//1.检查参数
if (dto!=null&& StringUtils.isNotBlank(dto.getSearchWords())){
//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.filter(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);
//设置高亮 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);
//处理响应结果
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);
}
}
基本上就这些,然后出来的效果是这样的
这里再问下小伙伴们
粗粮和细糠你选谁呢
有什么问题欢迎大家在评论区提问,肯定回答,记得一键三连哟,每天更新