1.场景还原
近期,笔者项目中需要通过关键字来搜索与之相关的数据,es的全文搜索终于派上用场了!
2.准备步骤
①原理分析:
es主要采用倒排索引,即每一个文档都对应一个ID。倒排索引会按照指定语法对每一个文档进行分词,然后维护一张表,列举所有文档中出现的terms以及它们出现的文档ID和出现频率。搜索时同样会对关键词进行同样的分词分析,然后查表得到结果。
②先下载与项目中es版本对应的ik中文分词器,https://github.com/medcl/elasticsearch-analysis-ik
③在es的plugins目录下创建ik,然后解压缩ik
④在elasticsearch.yml配置ik属性
index.analysis.analyzer.default.tokenizer : "ik_max_word"
index.analysis.analyzer.default.type : "ik"
3.实现方案
/**
* 全文索引
* @param index
* @param type
* @return
*/
public List hotCitySearchByEs(String index, String type,String startCity, String endCity,SortBuilder sortBuilder,QueryBuilder queryBuilder,Integer pageNo,Integer pageSize) {
TransportClient client = getClient();
//查询条件 在匹配文字的时候一定用matchQuery termQuery 用于精确匹配 匹配数字 ,long型 term查询不会分词
//matchQuery自带分词;
//termQuery不带分词器
QueryBuilder qb = boolQuery().must(termQuery("pinStartPoint", startCity))
.must(termQuery("pinEndPoint", endCity));
//索引
SearchResponse response = client.prepareSearch(index)
//type
.setTypes(type)
//搜索类型
.setSearchType(SearchType.DFS_QUERY_THEN_FETCH)
// Query
.setQuery(qb)
//排序
.addSort(sortBuilder)
//过滤
.setPostFilter(queryBuilder)
//分页
.setFrom(pageNo).setSize(pageSize).setExplain(true)
//执行
.execute()
.actionGet();
return response2List(client,response);
}
/**
* 将查询后获得的response转成list
* @param client
* @param response
* @return zx
*/
public static List response2List(TransportClient client,SearchResponse response){
SearchHits hits = response.getHits();
List<Map<String, Object>> list = new ArrayList<Map<String,Object>>();
for (int i = 0; i < hits.getHits().length; i++) {
BigDecimal geoDis = new BigDecimal((Double) hits.getAt(i).getSortValues()[0]);
Map<String, Object> map = hits.getAt(i).getSource();
map.put(EsProperties.ES_SERVICE_DISTANCE_TO,geoDis);
list.add(map);
}
client.close();
return list;
}
好了,今天点到为止,我是张星,欢迎加入博主技术交流群,群号:526601468