Elasticsearch中文搜索问题,单字可以,多字不行的问题。
第一使用IK分词器,版本要对应,下载到elasticsearch/plugin目录下,并新建ik目录
第二步配置elasticsearch
@Configuration
public class ElasticSearchClientConfig {
@Bean
public RestHighLevelClient restHighLevelClient(){
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(
new HttpHost("127.0.0.1", 9200, "http")));
return client;
}
}
第三配置实体类
@Document注解之后,默认情况下这个实体中所有的属性都会被建立索引、并且分词。
* 我们通过@Field注解来进行详细的指定,如果没有特殊需求,那么只需要添加@Document即可。
* @Field这里ik_max_word是按最细粒度分词,ik_smart是按最粗粒度分词。
*在搜索的时候用粗粒度,在写入的时候用细粒度。
* @author jun
* @since 2020-06-06
*/
@Document(indexName = "article",type = "article")
public class Article implements Serializable {
@Field(type = FieldType.Text, searchAnalyzer = "ik_smart", analyzer = "ik_max_word")
private String title;
@Document注解之后,默认情况下这个实体中所有的属性都会被建立索引、并且分词。
@Field这里ik_max_word是按最细粒度分词,ik_smart是按最粗粒度分词
第四实现精确搜索:
term不会分词。而keyword字段也不分词。需要完全匹配才可以,但ik分词器会默认分割,所以这里使用matchPhraseQuery。
@Override
public List<Map<String, Object>> searchPageHighlightBuilder(String keyword, Integer currentPage, Integer pageSize) throws Exception {
/**
if(currentPage == null ||currentPage <1){
currentPage=1;
}
// 页数
if (pageSize == null || pageSize < 1) {
pageSize = 3;
}
*/
//条件搜索
SearchRequest searchRequest = new SearchRequest("article");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//分页
//sourceBuilder.from(currentPage);
//sourceBuilder.size(pageSize);
//精准匹配
//TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("title", keyword.toLowerCase());
MatchPhraseQueryBuilder matchPhraseQueryBuilder = QueryBuilders.matchPhraseQuery("title", keyword);
sourceBuilder.query(matchPhraseQueryBuilder);
sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
//高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("title");
highlightBuilder.requireFieldMatch(false);//多个高亮显示
highlightBuilder.preTags("<span style=\"color:red\">");
highlightBuilder.postTags("</span>");
sourceBuilder.highlighter(highlightBuilder);
//执行搜索
searchRequest.source(sourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(searchResponse);
//解析结果
ArrayList<Map<String,Object>> list = new ArrayList<>();
for (SearchHit documentFields:searchResponse.getHits()){
//获取高亮字段
Map<String, HighlightField> highlightFields = documentFields.getHighlightFields();
HighlightField title = highlightFields.get("title");
Map<String, Object> sourceAsMap = documentFields.getSourceAsMap();//原来的结果
//解析高亮字段,将原来的字段换为我们高亮字段即可
if(title!=null){
Text[] fragments = title.fragments();
String n_title="";
for(Text text:fragments){
n_title += text;
}
sourceAsMap.put("title",n_title);//高亮字段替换原来的内容
}
list.add(sourceAsMap);
}
return list;
}