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,";"));
    }
}

 

 测试结果

 

附:

Elasticsearch-suggest官网

posted @ 2022-08-26 10:17  代码羡  阅读(515)  评论(0编辑  收藏  举报