Spring Boot + elasticsearch7 自动补全
想要实现一个类似的功能,输入关键词之后可以自动提示一些内容。
最简单的一种实现方式,在保留原字段索引功能不变的情况下,通过"一个字段对应多种类型”的方式,完成自动补全功能。
这样的话,通过实体类中的@Field注解就无法完成了,需要引入自定义的mapping。
新建一个article.json,存放在 resources/mapping下
{ "properties": { "name": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart", "fields": { "suggest": { "type": "completion", "analyzer": "standard" } } }, "desc": { "type": "text", "analyzer": "ik_max_word", "search_analyzer": "ik_smart" } } }
新建文章实体类Article.java,通过@Mapping注解引入自定义Mapping
@Data @Document(indexName = "article") @Setting(settingPath = "/setting/pinyin.analyzer.json") @Mapping(mappingPath = "/mapping/article.json") public class Article { @Id private Integer id; private String name; private String desc; }
新建接口SuggestDao.java
public interface SuggestDao { List<String> nameSuggest(String suggestKeyword); }
接口实现类
@Component public class SuggestDaoImpl implements SuggestDao { @Autowired private ElasticsearchRestTemplate restTemplate; @Override public List<String> nameSuggest(String suggestKeyword) { List<String> result = new ArrayList<>(); //自动补全字段为name,通过name.suggest调用自动补全功能 CompletionSuggestionBuilder completionSuggestionBuilder = SuggestBuilders.completionSuggestion("name.suggest") .size(5) .skipDuplicates(true); //通过SuggestBuilder传递要补全的内容 //suggest_text是一个存储标识,随便写一个就可,下文调用的时候保持一致即可 SuggestBuilder suggestBuilder = new SuggestBuilder(); suggestBuilder.addSuggestion("suggest_text", completionSuggestionBuilder).setGlobalText(suggestKeyword); //article为索引名称 Suggest suggest = restTemplate.suggest(suggestBuilder, IndexCoordinates.of("article")).getSuggest(); CompletionSuggestion suggest_text = suggest.getSuggestion("suggest_text"); for (CompletionSuggestion.Entry entry : suggest_text.getEntries()) { for (CompletionSuggestion.Entry.Option option : entry.getOptions()) { result.add(option.getText().toString()); } } return result; } }
启动项目之后,再通过kibana导入一些数据进行测试
POST article/_doc/1001
{
"name":"新西游记"
}
POST article/_doc/1002
{
"name":"新红楼梦"
}
POST article/_doc/1003
{
"name":"新三国"
}
POST article/_doc/1004
{
"name":"新水浒"
}
POST article/_doc/1005
{
"name":"水浒少年",
"desc":"三藏,御弟,金蝉子"
}
测试类
@SpringBootTest @Slf4j class SuggestDaoTest { @Autowired private SuggestDao suggestDao; @Test void nameSuggest() { String key = "新"; List<String> list = suggestDao.nameSuggest(key); printList(key,list); String key2 = "水浒"; List<String> list2 = suggestDao.nameSuggest(key2); printList(key2,list2); } private void printList(String key, List<String> list) { log.info("‘{}’的自动补全内容如下:{}",key, StringUtil.join(list,";")); } }
测试结果
附: