springboot集成ElasticSearch使用completion实现补全功能

本文涉及的产品
检索分析服务 Elasticsearch 版,2核4GB开发者规格 1个月
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
简介: springboot集成ElasticSearch使用completion实现补全功能

@[TOC]

摘要

所谓自动补全功能就是“百度搜索框”中每敲下一个字符下面的提示框就会动态改变提示的功能,就是下面的效果:↓
image.png
image.png

==说明:使用RestHighLevelClient 即可实现输入框补全功能==

  • springboot代码
  • kibana代码

springboot代码

依赖

<!--ES-->
<dependency>
    <groupId>org.elasticsearch.client</groupId>
    <artifactId>elasticsearch-rest-high-level-client</artifactId>
    <version>6.8.12</version>
    <exclusions>
        <exclusion>
            <artifactId>elasticsearch</artifactId>
            <groupId>org.elasticsearch</groupId>
        </exclusion>
    </exclusions>
</dependency>
<dependency>
    <groupId>org.elasticsearch</groupId>
    <artifactId>elasticsearch</artifactId>
    <version>6.8.12</version>
</dependency>

代码

import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
@Autowired
private RestHighLevelClient client;
public static final int NINE = 9;
public static final int TEN = 10;

/**
     *  输入框自动补全提示功能(ElasticSearch使用completion实现补全功能)
     * @param request request
     * @param suggestValue 输入参数
     * @author liudz
     * @date 2021/4/19
     * @return 执行结果
     **/
    @GetMapping(value = "/completion")
    public Response<List<String>> getSuggestCompletion(@RequestParam String suggestValue, HttpServletRequest request) {
   
        log.info("--getSearchSuggest--begin--");
        Long userId = Long.valueOf(request.getUserPrincipal().getName());
        //指定在哪个字段搜索
        String suggestField = "region";

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //suggestField为指定在哪个字段搜索,suggestValue为输入内容,TEN为10,代表输出显示最大条数
        CompletionSuggestionBuilder suggestionBuilderDistrict =
                new CompletionSuggestionBuilder(suggestField).prefix(suggestValue).size(TEN);
        SuggestBuilder suggestBuilder = new SuggestBuilder();
        suggestBuilder.addSuggestion("my_suggest", suggestionBuilderDistrict);
        searchSourceBuilder.suggest(suggestBuilder);
        SearchRequest searchRequest = new SearchRequest(userId + esIndex);
        searchRequest.types(esType);
        searchRequest.source(searchSourceBuilder);
        SearchResponse response = null;
        try {
   
            response = client.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
   
            log.error("IOException:{}", e);
        }
        Suggest suggest = response.getSuggest();

        List<String> keywords = null;
        if (suggest != null) {
   
            keywords = new ArrayList<>();
            List<? extends Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option>> entries =
                    suggest.getSuggestion("my_suggest").getEntries();
            for (Suggest.Suggestion.Entry<? extends Suggest.Suggestion.Entry.Option> entry: entries) {
   
                for (Suggest.Suggestion.Entry.Option option: entry.getOptions()) {
   
                    String keyword = option.getText().string();
                    if (!StringUtils.isEmpty(keyword)) {
   
                        if (keywords.contains(keyword)) {
   
                            continue;
                        }
                        keywords.add(keyword);
                        if (keywords.size() >= NINE) {
   
                            break;
                        }
                    }
                }
            }
        }
        return Response.success(keywords);
    }

kibana代码

第一部分:设置index、type、mapping

==说明:设置某个字段"type": "completion"即可==

PUT 12_assets_directory_v1/
{
   
  "index_patterns": "test-logs-*",
  "settings": {
   
        "number_of_shards": 5,
        "number_of_replicas": 1,
        "analysis": {
   
      "analyzer": {
   
        "my_analyzer": {
   
          "type": "pattern",
          "pattern":["_","-"]
        }
      }
    }
    },
  "mappings": {
   
    "_doc":{
   
      "properties": {
   
                "file_name": {
   
                    "type": "text",
                    "copy_to": "region"
                },
                "file_type": {
   
                  "type": "keyword"
                },
                "database_name": {
   
                    "type": "text",
                    "analyzer": "ik_max_word",
                    "copy_to": "region"
                },
                "table_name": {
   
                    "type": "text",
                    "analyzer": "ik_max_word",
                    "copy_to": "region"
                },
                "include_fields": {
   
                    "type": "text",
                    "index": false
                },
                "source_business": {
   
                    "type": "integer",
                    "index": false
                },
                "store_type": {
   
                    "type": "text",
                    "index": false
                },
                "whether_online": {
   
                    "type": "byte",
                    "index": false
                },
                "foreign_id": {
   
                    "type": "integer",
                    "index": false
                },
                "update_time": {
   
                    "type": "long",
                    "index": false
                },
                "region": {
   
                      "type": "completion",
                      "analyzer": "ik_max_word"
      }
            }
    }
  }
}

第二部分:批量插入

==批量插入每个json必须单独存在一行==

POST _bulk/?refresh=true
{
    "index" : {
    "_index" : "12_assets_directory_v1","_type" : "_doc" }}
{
    "file_name": "Lucene is cool","file_type": "file","database_name": "","table_name": "","include_fields": "","source_business": 1,"store_type": "hdfs","whether_online": 0,"foreign_id": 10,"update_time": 1618560193000}
{
    "index" : {
    "_index" : "12_assets_directory_v1","_type" : "_doc" }}
{
    "file_name": "Lucene用户文件","file_type": "file","database_name": "","table_name": "","include_fields": "","source_business": 1,"store_type": "hdfs","whether_online": 0,"foreign_id": 11,"update_time": 1618560193010}
{
    "index" : {
    "_index" : "12_assets_directory_v1","_type" : "_doc" }}
{
    "file_name": "103-is-cool","file_type": "file","database_name": "","table_name": "","include_fields": "","source_business": 1,"store_type": "hdfs","whether_online": 0,"foreign_id": 12,"update_time": 1618560193040}
{
    "index" : {
    "_index" : "12_assets_directory_v1","_type" : "_doc" }}
{
    "file_name": "103_is_cool","file_type": "file","database_name": "","table_name": "","include_fields": "","source_business": 1,"store_type": "hdfs","whether_online": 0,"foreign_id": 20,"update_time": 1618560193120}
{
    "index" : {
    "_index" : "12_assets_directory_v1","_type" : "_doc" }}
{
    "file_name": "103 is cool","file_type": "file","database_name": "","table_name": "","include_fields": "","source_business": 1,"store_type": "hdfs","whether_online": 0,"foreign_id": 17,"update_time": 1618560193070}
{
    "index" : {
    "_index" : "12_assets_directory_v1","_type" : "_doc" }}
{
    "file_name": "test001","file_type": "file","database_name": "","table_name": "","include_fields": "","source_business": 1,"store_type": "hdfs","whether_online": 0,"foreign_id": 18,"update_time": 1618560193080}
{
    "index" : {
    "_index" : "12_assets_directory_v1","_type" : "_doc" }}
{
    "file_name": "test002 ldz","file_type": "file","database_name": "","table_name": "","include_fields": "","source_business": 1,"store_type": "hdfs","whether_online": 0,"foreign_id": 19,"update_time": 1618560193090}
{
    "index" : {
    "_index" : "12_assets_directory_v1","_type" : "_doc" }}
{
    "file_name": "美丽心之所想","file_type": "file","database_name": "","table_name": "","include_fields": "","source_business": 1,"store_type": "hdfs","whether_online": 0,"foreign_id": 13,"update_time": 1618560193050}
{
    "index" : {
    "_index" : "12_assets_directory_v1","_type" : "_doc" }}
{
    "file_name": "魅力","file_type": "file","database_name": "美好","table_name": "","include_fields": "","source_business": 1,"store_type": "hdfs","whether_online": 0,"foreign_id": 14,"update_time": 1618560193060}
{
    "index" : {
    "_index" : "12_assets_directory_v1","_type" : "_doc" }}
{
    "file_name": "","file_type": "table","database_name": "geespace_bd_platform_dev","table_name": "12_mysql-1","include_fields": "","source_business": 1,"store_type": "mysql","whether_online": 0,"foreign_id": 10,"update_time": 1618560193020}
{
    "index" : {
    "_index" : "12_assets_directory_v1","_type" : "_doc" }}
{
    "file_name": "","file_type": "table","database_name": "geespace_bd_platform_dev","table_name": "103_addserialnumber_2","include_fields": "","source_business": 1,"store_type": "mysql","whether_online": 0,"foreign_id": 11,"update_time": 1618560193030}

第三部分:执行

==“song-suggest”为自定义的别名,“field”为要查询的字段==

POST 12_assets_directory_v1/_search?pretty
{
   
  "suggest": {
   
    "song-suggest": {
   
      "prefix": "g",
      "completion": {
   
        "field": "region"
      }
    }
  }
}

第四部分:结果展示

==返回json中options集合中的text即为补全提示的内容==

{
   
  "took" : 5,
  "timed_out" : false,
  "_shards" : {
   
    "total" : 5,
    "successful" : 5,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
   
    "total" : 0,
    "max_score" : 0.0,
    "hits" : [ ]
  },
  "suggest" : {
   
    "song-suggest" : [
      {
   
        "text" : "g",
        "offset" : 0,
        "length" : 1,
        "options" : [
          {
   
            "text" : "geespace_bd_platform_dev",
            "_index" : "12_assets_directory_v1",
            "_type" : "_doc",
            "_id" : "jIkR6HgBdsS-EtqKoYwv",
            "_score" : 1.0,
            "_ignored" : [
              "region"
            ],
            "_source" : {
   
              "file_name" : "",
              "file_type" : "table",
              "database_name" : "geespace_bd_platform_dev",
              "table_name" : "12_mysql-1",
              "include_fields" : "",
              "source_business" : 1,
              "store_type" : "mysql",
              "whether_online" : 0,
              "foreign_id" : 10,
              "update_time" : 1618560193020
            }
          },
          {
   
            "text" : "geespace_bd_platform_dev",
            "_index" : "12_assets_directory_v1",
            "_type" : "_doc",
            "_id" : "jYkR6HgBdsS-EtqKoYwv",
            "_score" : 1.0,
            "_ignored" : [
              "region"
            ],
            "_source" : {
   
              "file_name" : "",
              "file_type" : "table",
              "database_name" : "geespace_bd_platform_dev",
              "table_name" : "103_addserialnumber_2",
              "include_fields" : "",
              "source_business" : 1,
              "store_type" : "mysql",
              "whether_online" : 0,
              "foreign_id" : 11,
              "update_time" : 1618560193030
            }
          }
        ]
      }
    ]
  }
}

本人先关其他文章链接

1.ElasticSearch7.6.x 模板及滚动索引创建及注意事项
https://blog.csdn.net/a924382407/article/details/115082265

2.ElasticSearch的IK分词器
https://blog.csdn.net/a924382407/article/details/117255506

3.ElasticSearch核心概念:倒排索引
https://blog.csdn.net/a924382407/article/details/117255449

4.springboot集成ElasticSearch使用completion实现补全功能
https://blog.csdn.net/a924382407/article/details/115868167

5.ES Restful API讲解使用
https://blog.csdn.net/a924382407/article/details/115085022

6.ES API,使用Kibana的开发工具用例说明
https://blog.csdn.net/a924382407/article/details/115084549

相关实践学习
使用阿里云Elasticsearch体验信息检索加速
通过创建登录阿里云Elasticsearch集群,使用DataWorks将MySQL数据同步至Elasticsearch,体验多条件检索效果,简单展示数据同步和信息检索加速的过程和操作。
ElasticSearch 入门精讲
ElasticSearch是一个开源的、基于Lucene的、分布式、高扩展、高实时的搜索与数据分析引擎。根据DB-Engines的排名显示,Elasticsearch是最受欢迎的企业搜索引擎,其次是Apache Solr(也是基于Lucene)。 ElasticSearch的实现原理主要分为以下几个步骤: 用户将数据提交到Elastic Search 数据库中 通过分词控制器去将对应的语句分词,将其权重和分词结果一并存入数据 当用户搜索数据时候,再根据权重将结果排名、打分 将返回结果呈现给用户 Elasticsearch可以用于搜索各种文档。它提供可扩展的搜索,具有接近实时的搜索,并支持多租户。
目录
相关文章
|
24天前
|
Java API 数据库
构建RESTful API已经成为现代Web开发的标准做法之一。Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐。
【10月更文挑战第11天】本文介绍如何使用Spring Boot构建在线图书管理系统的RESTful API。通过创建Spring Boot项目,定义`Book`实体类、`BookRepository`接口和`BookService`服务类,最后实现`BookController`控制器来处理HTTP请求,展示了从基础环境搭建到API测试的完整过程。
37 4
|
26天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 实现动态路由和菜单功能,快速搭建前后端分离的应用框架。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,包括版本兼容性、安全性、性能调优等方面。
132 1
|
21天前
|
Java API 数据库
Spring Boot框架因其简洁的配置、快速的启动特性及丰富的功能集而备受开发者青睐
本文通过在线图书管理系统案例,详细介绍如何使用Spring Boot构建RESTful API。从项目基础环境搭建、实体类与数据访问层定义,到业务逻辑实现和控制器编写,逐步展示了Spring Boot的简洁配置和强大功能。最后,通过Postman测试API,并介绍了如何添加安全性和异常处理,确保API的稳定性和安全性。
31 0
|
11天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,创建并配置 Spring Boot 项目,实现后端 API;然后,使用 Ant Design Pro Vue 创建前端项目,配置动态路由和菜单。通过具体案例,展示了如何快速搭建高效、易维护的项目框架。
90 62
|
7天前
|
前端开发 Java easyexcel
SpringBoot操作Excel实现单文件上传、多文件上传、下载、读取内容等功能
SpringBoot操作Excel实现单文件上传、多文件上传、下载、读取内容等功能
41 8
|
8天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能
本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个前后端分离的应用框架,实现动态路由和菜单功能。首先,确保开发环境已安装必要的工具,然后创建并配置 Spring Boot 项目,包括添加依赖和配置 Spring Security。接着,创建后端 API 和前端项目,配置动态路由和菜单。最后,运行项目并分享实践心得,帮助开发者提高开发效率和应用的可维护性。
23 2
|
21天前
|
人工智能 JavaScript 网络安全
ToB项目身份认证AD集成(三完):利用ldap.js实现与windows AD对接实现用户搜索、认证、密码修改等功能 - 以及针对中文转义问题的补丁方法
本文详细介绍了如何使用 `ldapjs` 库在 Node.js 中实现与 Windows AD 的交互,包括用户搜索、身份验证、密码修改和重置等功能。通过创建 `LdapService` 类,提供了与 AD 服务器通信的完整解决方案,同时解决了中文字段在 LDAP 操作中被转义的问题。
|
27天前
|
机器学习/深度学习 存储 运维
探索未来:结合机器学习功能拓展Elasticsearch应用场景
【10月更文挑战第8天】随着数据量的爆炸性增长,高效的数据存储、检索和分析变得越来越重要。Elasticsearch 作为一个分布式的搜索和分析引擎,以其强大的全文搜索能力、实时分析能力和可扩展性而闻名。近年来,随着机器学习技术的发展,将机器学习集成到 Elasticsearch 中成为了一种新的趋势,这不仅增强了 Elasticsearch 的数据分析能力,还开拓了一系列新的应用场景。
48 7
|
28天前
|
JavaScript 安全 Java
如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用
【10月更文挑战第8天】本文介绍了如何使用 Spring Boot 和 Ant Design Pro Vue 构建一个具有动态路由和菜单功能的前后端分离应用。首先,通过 Spring Initializr 创建并配置 Spring Boot 项目,实现后端 API 和安全配置。接着,使用 Ant Design Pro Vue 脚手架创建前端项目,配置动态路由和菜单,并创建相应的页面组件。最后,通过具体实践心得,分享了版本兼容性、安全性、性能调优等注意事项,帮助读者快速搭建高效且易维护的应用框架。
38 3
|
16天前
|
存储 Java 数据管理
强大!用 @Audited 注解增强 Spring Boot 应用,打造健壮的数据审计功能
本文深入介绍了如何在Spring Boot应用中使用`@Audited`注解和`spring-data-envers`实现数据审计功能,涵盖从添加依赖、配置实体类到查询审计数据的具体步骤,助力开发人员构建更加透明、合规的应用系统。
下一篇
无影云桌面