es7.4 默认不在支持指定索引类型,默认索引类型是_doc(隐含:include_type_name=false)
PUT /news_website
{
"mappings": {
"properties" : {
"title" : {
"type": "text",
"analyzer": "ik_max_word",
"fields": {
"suggest" : {
"type" : "completion",
"analyzer": "ik_max_word"
}
}
},
"content": {
"type": "text",
"analyzer": "ik_max_word"
}
}
}
}
首先查看索引库的mapping
第一种方式:基于completion suggest
测试代码如下:
@Test
public void testSuggestCompletionProc() {
String suggestField="title.suggest";//指定在哪个字段搜索
String suggestValue="西游";//输入的信息
Integer suggestMaxCount=2;//获得最大suggest条数
CompletionSuggestionBuilder suggestionBuilderDistrict = new CompletionSuggestionBuilder(suggestField).prefix(suggestValue).size(suggestMaxCount);
SuggestBuilder suggestBuilder = new SuggestBuilder();
suggestBuilder.addSuggestion("student_suggest", suggestionBuilderDistrict);//添加suggest
//设置查询builder的index,type,以及建议
SearchRequestBuilder requestBuilder = template.getClient().prepareSearch("news_website")
.setTypes("news").suggest(suggestBuilder);
System.out.println(requestBuilder.toString());
SearchResponse response = requestBuilder.get();
Suggest suggest = response.getSuggest();//suggest实体
Set<String> suggestSet = new HashSet<>();//set
int maxSuggest = 0;
if (suggest != null) {
Suggest.Suggestion result = suggest.getSuggestion("student_suggest");//获取suggest,name任意string
for (Object term : result.getEntries()) {
if (term instanceof CompletionSuggestion.Entry) {
CompletionSuggestion.Entry item = (CompletionSuggestion.Entry) term;
if (!item.getOptions().isEmpty()) {
//若item的option不为空,循环遍历
for (CompletionSuggestion.Entry.Option option : item.getOptions()) {
String tip = option.getText().toString();
/*float sco = option.getScore();
System.out.println(tip+"---"+sco);*/
if (!suggestSet.contains(tip)) {
suggestSet.add(tip);
++maxSuggest;
}
}
}
}
if (maxSuggest >= suggestMaxCount) {
break;
}
}
}
List<String> suggests = Arrays.asList(suggestSet.toArray(new String[]{}));
suggests.forEach((s)->{
System.out.println(s);
});
/*return suggests;*/
}
kibana语句如下:
GET /news_website/news/_search
{
"suggest": {
"my-suggest" : {
"prefix" : "西游",
"completion" : {
"field" : "title.suggest",
"size":10 ##显示前10条
}
}
}
}
第二种方式:基于Match Phrase Prefix Query
java代码如下:
public List<EsModel> prefixQuery(String name, String text){
// 构建查询条件
NativeSearchQueryBuilder queryBuilder = new NativeSearchQueryBuilder();
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
QueryBuilder basicQuery = boolQueryBuilder.must(QueryBuilders.matchPhrasePrefixQuery(name, text).maxExpansions(5));
queryBuilder.withQuery(basicQuery);
List<EsModel> list = template.queryForList(queryBuilder.build(), EsModel.class);
return list;
}
@RequestMapping("prefixQuery")
public List<EsModel> prefixQuery(){
List<EsModel> list = esUtils.prefixQuery("title", "西游");
return list;
}
kibana语句如下:
GET /news_website/news/_search
{
"query": {
"match_phrase_prefix": {
"title": {
"query": "西游"
}
}
},
"size":10 ##分页 一页显示10条
}
对比:
注意:第一种方式我使用的字段是title.suggest,原因是 设置了title.suggest字段为completion类型,因此使用了suggest的方式实现搜索提示;第二种方式我使用的字段是title,而title是text类型,所以直接使用elastic的原生查询检索到了结果,但是这样的结果有一部分是我们需要的,会检索出来一些垃圾数据,因此不推荐;同时在对比当中我们也看到了,如果第二种方式的字段我们也使用title.suggest,也达到了预期的结果;究竟用这两种方式哪一种好一点,目前我也不大清楚,有知道的大神欢迎提出了。
索引库创建参考:https://blog.youkuaiyun.com/wuzhiwei549/article/details/80530992
java程序代码参考:https://blog.youkuaiyun.com/wangxudongx/article/details/87275232
Match Phrase Query 和 Match Phrase Prefix Query比较:https://www.cnblogs.com/reycg-blog/p/10012238.html