环境准备:
Elasticsearch服务器
ik中文分词器
Kibana服务
一个集成了ES的springboot项目
博主环境:
es:6.2.2 Kibana:6.2.2 springboot:2.1.2
实现目标:建立学生数据索引,以学生姓名为搜索自动补全字段。
学生实体类:
@Document(indexName = "student_index",type="student")
public class Student implements Serializable {
@Id
@Field(type= FieldType.Auto)
private String studentId;
@Override
public String toString() {
return "Student{" +
"studentId='" + studentId + '\'' +
", name='" + name + '\'' +
", age=" + age +
", scores=" + scores +
'}';
}
public Student(String studentId, String name, Integer age, List<Double> scores) {
this.studentId = studentId;
this.name = name;
this.age = age;
this.scores = scores;
}
public Student() {
}
public String getStudentId() {
return studentId;
}
public void setStudentId(String studentId) {
this.studentId = studentId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
public List<Double> getScores() {
return scores;
}
public void setScores(List<Double> scores) {
this.scores = scores;
}
@Field(type=FieldType.Auto)
private String name;
@Field(type=FieldType.Auto)
private Integer age;
@Field(type=FieldType.Auto)
private List<Double> scores;
}
建立学生的索引和映射:
待搜索的字段需要设置为Completion类型
PUT /student_index
{
"mappings": {
"student" : {
"properties" : {
"name" : {
"type" : "completion",
"analyzer": "ik_smart"
},
"age" : {
"type" : "integer"
},
"studentId" : {
"type" : "text"
},
"scores":{
"type" : "float"
}
}
}
}
}
整点数据测试一下:
学生索引Repository类:
@Repository
public interface StudentRepository extends ElasticsearchCrudRepository<Student,String>{
}
开始测试:
在程序里插入一些数据;
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Test
public void contextLoads() {
List scores= new ArrayList<>();
scores.add(67.2);
scores.add(27.2);
scores.add(56.2);
/* studentIndexRepository.save(new Student(UUID.randomUUID().toString(), "张三", 21, scores ));
studentIndexRepository.save(new Student(UUID.randomUUID().toString(), "李四", 35, scores ));
studentIndexRepository.save(new Student(UUID.randomUUID().toString(), "王二", 45, scores ));
studentIndexRepository.save(new Student(UUID.randomUUID().toString(), "张大林", 23, scores ));
studentIndexRepository.save(new Student(UUID.randomUUID().toString(), "王大力", 51, scores ));*/
studentIndexRepository.save(new Student(UUID.randomUUID().toString(), "刘伯", 21, scores ));
studentIndexRepository.save(new Student(UUID.randomUUID().toString(), "刘思想", 35, scores ));
studentIndexRepository.save(new Student(UUID.randomUUID().toString(), "王皮皮", 45, scores ));
studentIndexRepository.save(new Student(UUID.randomUUID().toString(), "王二丫", 23, scores ));
studentIndexRepository.save(new Student(UUID.randomUUID().toString(), "王铁蛋", 51, scores ));
}
在Kibana测试
POST /student_index/completion/_search
{ "size": 0,
"suggest": {
"name-suggest": {
"prefix": "王二",
"completion": {
"field": "name"
}
}
}
}
结果正确:
接下来是实现获取suggest的代码:
@Test
public void testSuggestCompletionProc() {
String suggestField="name";//指定在哪个字段搜索
String suggestValue="王二";//输入的信息
Integer suggestMaxCount=10;//获得最大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 = this.elasticsearchTemplate.getClient().prepareSearch("student_index").setTypes("student").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();
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;
}
输出结果正确: