从安装到使用ElasticSearch

使用ElasticSearch

参考文献:https://blog.csdn.net/yb546822612/article/details/103196486

一、搜索引擎简介

1、Elasticsearch简介

Elasticsearch是一个实时分布式搜索和分析引擎。它让你以前所未有的速度处理大数据成为可能。

它用于全文搜索结构化搜索分析以及将这三者混合使用

维基百科使用Elasticsearch提供全文搜索并高亮关键字,以及输入实时搜索(search-asyou-type)和搜索纠错(did-you-mean)等搜索建议功能。

英国卫报使用Elasticsearch结合用户日志和社交网络数据提供给他们的编辑以实时的反馈,以便及时了解公众对新发表的文章的回应。
StackOverflow结合全文搜索与地理位置查询,以及more-like-this功能来找到相关的问题和答案。

Github使用Elasticsearch检索1300亿行的代码。

但是Elasticsearch不仅用于大型企业,它还让像DataDog以及Klout这样的创业公司将最初的想法变成可扩展的解决方案。Elasticsearch可以在你的笔记本上运行,也可以在数以百计的服务器上处理PB级别的数据 。

Elasticsearch是一个基于Apache Lucene™的开源搜索引擎。无论在开源还是专有领域,Lucene可以被认为是迄今为止最先进、性能最好的、功能最全的搜索引擎库。

但是,Lucene只是一个库。想要使用它,你必须使用Java来作为开发语言并将其直接集成到你的应用中,更糟糕的是,Lucene非常复杂,你需要深入了解检索的相关知识来理解它是如何工作的。

Elasticsearch也使用Java开发并使用Lucene作为其核心来实现所有索引和搜索的功能,但是它的目的是通过简单的 RESTful API 来隐藏Lucene的复杂性,从而让全文搜索变得简单。

2、Solr简介

Solr是一个独立的企业级搜索应用服务器

Solr 是Apache下的一个顶级开源项目,采用Java开发,它是基于Lucene的全文搜索服务器。Solr提供了比Lucene更为丰富的查询语言,同时实现了可配置、可扩展,并对索引、搜索性能进行了优化

Solr可以独立运行,运行在Jetty、Tomcat等这些Servlet容器中,Solr 索引的实现方法很简单,用 POST 方法向 Solr 服务器发送一个描述 Field 及其内容的 XML 文档,Solr根据xml文档添加、删除、更新索引 。Solr 搜索只需要发送 HTTP GET 请求,然后对 Solr 返回Xml、json等格式的查询结果进行解析,组织页面布局。Solr不提供构建UI的功能,Solr提供了一个管理界面,通过管理界面可以查询Solr的配置和运行情况。

solr是基于lucene开发企业级搜索服务器,实际上就是封装了lucene。

Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口。用户可以通过http请求,向搜索引擎服务器提交一定格式的文件,生成索引;也可以通过提出查找请求,并得到返回结果。

3、Lucene简介

Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。人们经常提到信息检索程序库,虽然与搜索引擎有关,但不应该将信息检索程序库与搜索引擎相混淆。

Lucene是一个全文检索引擎的架构。那什么是全文搜索引擎?

全文搜索引擎是名副其实的搜索引擎,国外具代表性的有Google、Fast/AllTheWeb、AltaVista、Inktomi、Teoma、WiseNut等,国内著名的有百度(Baidu)。它们都是通过从互联网上提取的各个网站的信息(以网页文字为主)而建立的数据库中,检索与用户查询条件匹配的相关记录,然后按一定的排列顺序将结果返回给用户,因此他们是真正的搜索引擎。

从搜索结果来源的角度,全文搜索引擎又可细分为两种,一种是拥有自己的检索程序(Indexer),俗称“蜘蛛”(Spider)程序或“机器人”(Robot)程序,并自建网页数据库,搜索结果直接从自身的数据库中调用,如上面提到的7家引擎;另一种则是租用其他引擎的数据库,并按自定的格式排列搜索结果,如Lycos引擎。

4、Elasticsearch和Solr比较

img

img

img

img

5、ElasticSearch vs Solr 总结

  1. Es基本是开箱即用,非常简单。Solr安装略复杂一丢丢
  2. Solr利用Zookeeper进行分布式管理,而ElasticSearch自身带有分布式协调管理功能。
  3. Solr支持更多格式的数据,比如Json、xml、csv,而ElasticSearch仅支持Json文件格式。
  4. Solr官方提供的功能更多,而ElasticSearch本身就注重于核心功能,高级功能多有第三方插件提供,例如图形化界面需要Kibana友好支撑
  5. Solr查询快,但是更新索引慢(即插入删除慢),用于电商等查询多的应用;
    • ES建立索引快(即查询慢),即实时性查询快,用于facebook新浪等搜索。
    • Solr是传统搜索应用的有力解决方案,但ElasticSearch更适用于新兴的实时搜索应用
  6. Solr比较成熟,有一个更大,更成熟的用户、开发和贡献社区,而ElasticSearch相对开发维护者较少,更新太快,学习使用成本较高。

二、ElasticSearch安装

最低需求:jdk1.8 保证jdk环境正常

官网下载地址:https://www.elastic.co/cn/downloads/elasticsearch

华为镜像站下载地址:https://mirrors.huaweicloud.com/elasticsearch/?C=N&O=D 【下载速度快】

1、下载解压

image-20211014145412694

文件目录:

bin:可执行文件
config:配置文件
	elasticsearch.yml:ElasticSearch配置文件
	jvm.options:配置虚拟机 、
lib:jar依赖包
modules:功能模块
logs:日志
plugins:插件

2、启动服务

进入bin目录执行elasticsearch.bat可执行文件,等待服务启动完成,访问localhost:9200端口

image-20211014151139797

测试访问:

image-20211014150911506

一个ElasticSearch也算是一个集群,cluster_name:集群名称 和 uuid

3、安装可视化工具

需要Nodejs环境

方便观察ElasticSearch中的数据信息

下载地址:https://github.com/mobz/elasticsearch-head

下载后解压文件目录,进入到解压后的文件目录

#打开cmd命令窗口,需要注意一定要在当前文件目录中 即elasticsearch-head-master目录下
npm install
#启动服务
npm run start
# 访问9100端口

启动成功如图:

image-20211014153057690

image-20211014153125757配置跨域:

默认情况下,可视化面板无法连接到9200端口

配置跨域进行解决

  1. 关闭ElasticSearch(关闭运行ElasticSearch的命令窗口)

  2. 打开ElasticSearch的配置文件目录

  3. 修改elasticsearch.yml文件,添加以下代码

    #跨域配置
    http.cors.enabled: true
    http.cors.allow-origin: "*"
    
  4. 重启ElasticSearch

测试访问

image-20211014154225334

4、安装Kibana

需要有Nodejs环境

安装Kibana为了方便后面的测试,当然也可以使用前面安装的可视化工具进行测试,但是它没有json格式化,非常的麻烦

常用测试工具:Postman、curl、谷歌浏览器插件

这里就使用Kibana,安装Kibana之后ElasticSearch会自动添加Kibana的索引

下载地址:https://www.elastic.co/cn/downloads/kibana#ga-release

  1. 下载解压后进入bin目录,执行kibana.bat文件

    image-20211014161703640

  2. 访问5601端口

  3. image-20211014162226198

  4. 找到工具选项

    image-20211014162707361

    之后的所有工作都在这里进行

    image-20211014162824402

修改Kibana语言

Kibana提供了对中文的支持,需要修改Kibana配置文件即可

image-20211014163344183

进入Kibana安装目录下的conf目录,修改kibana.xml文件

#修改语言 默认是英文(en)
i18n.locale: "zc-CN"

重启项目!汉化完成

image-20211014164534708

三、ES核心概念

  1. 索引
  2. 字段类型(mapping)
  3. 文档(documents)
  4. 分片(倒排索引)

elasticsearch是面向文档,关系行数据库和elasticsearch客观的对比!一切都是JSON!

Relational DBElasticsearch
数据库(database)索引
表(tables)types
行(rows)documents
字段(columns)fields

一个elasticsearch就是一个集群,默认集群名称就是elasticsearch

image-20211014174538350

elasticsearch(集群)中可以包含多个索引(数据库),每个索引中可以包含多个类型(表)

每个类型下又包含多个文档(行),每个文档中又包含多个字段(列)

索引

物理设计:
elasticsearch在后台把每个索引划分成多个分片,每个分片可以在集群中的不同服务器之间迁移

逻辑设计:

一个索引中,包含多个文档,比如说文档1,文档2。当我们索引一篇文档时,可以通过这样的一个顺序找到它:索引 > 类型 > 文档id,通过这个组合我们就能索引到某个具体的文档。注意:ID不必是整数,实际上它是一个字符串。

文档

就是我们的一条条数据

ElasticSearch是面向文档的,那么就意味着索引和搜索数据的最小单位是文档,ElasticSearch中,文档有几个重要属性:

  • 自我包含,一篇文档同时包含字段和对应的值,也就是同时包含 key:value
  • 可以是层次型的,一个文档中包含自文档,复杂的逻辑实体就是这么来的
  • 灵活的结构,文档不依赖预先定义的模式,我们知道关系型数据中,要提前设置好字段才能使用,在ElasticSearch中,对于字段是非常灵活的,有时候,我们可以忽略改字段,或者动态的添加一个新字段。

尽管我们可以随意的新增或者忽略某个字段,但是,每个字段的类型非常重要,比如一个年龄字段类型,可以是字符串,也可以是整形。

因为ElasticSearch会保存字段和类型之间的映射及其他的设置。这种映射具体到每个映射的每种类型,这也是为什么在ElasticSearch中,类型有时候也称为映射类型。

类型

类型是文档的逻辑容器,就像关系型数据库一样,表格是行的容器。类型中对于字段的定义称为映射,比如name映射为字符串类型。

我们说文档是无模式的,它们不需要拥有映射中所定义的所有字段,比如新增一个字段,那么ElasticSearch是怎么做的呢?

ElasticSearch会自动的将新字段加入映射,但是这个字段不确定它是什么类型,ElasticSearch就开始猜,如果这个值是18,那么ElasticSearch会认为它是整形。

但是ElasticSearch不一定都会猜对,所以最安全的方式就是提前定义好所需要的映射,这点跟关系型数据库殊途同归了。先定义好字段,后使用

索引

就是数据库

索引是映射类型的容器,ElasticSearch中的索引是一个非常大的文档集合。索引存储了映射类型的字段和其他设置。然后它们被存储到了各个分片上了。

物理设计:节点和分片 如何工作

image-20211014235033570

一个集群至少有一个节点,而一个节点就是一个ElasticSearch进程,节点可以有多个索引默认的,如果你创建索引,那么索引将会有个5分片(primary shard,又称主分片) 构成的,没一个主分片会有一个副本(replica shard,又称为复制分片)

image-20211014235110838

上图是一个有3个节点的集群,可以看到主分片和对应的复制分片都不会在同一个节点内,这样有利于某个节点挂掉了,数据也不至于丢失。

实际上,一个分片是一个Lucene索引,一个包含 倒排索引的文件目录,倒排索引的结构使得ElasticSearch在不扫描全部文档的情况下,就能告诉i哪些文档包含特定的关键字。

倒排索引

ElasticSearch使用的是一种称为倒排索引的结构,采用Lucene倒排索引作为底层。这种结构适用于快速的全文搜素,一个索引由文档中所有不重复的列表构成,对于每一个词,都有一个包含它的文档列表。

例如:

image-20211015145023113

如果要搜索含有python标签的文章,那相对于查找所有原始数据而言,查找倒排索引后的数据将会快很多。只需要查看标签这一栏,直接获取相关文章id即可

过滤掉无关数据,提高效率!

  • ElasticSearch的索引和Lucene的索引对比

    在ElasticSearch中,索引这个词被频繁使用,这就是术语的使用。在ElasticSearch中,索引被分成多个分片,每份分片是一个Lucene的索引。

    所以一个ElasticSearch索引是由多个Lucene索引组成。

四、IK分词器

简单来说就是把一句话或一段话进行合理拆分

比如说:我爱中国 ,使用分词器后可以分为:我、我爱、爱、中国

image-20211015150352879

分词器根据输入的一段文字进行合理分词,然后再通过分词后的关键词进行搜索文档内容。

默认情况下分词只对英文有效,所以我们需要安装ik分词器进行支持中文分词

一、下载安装IK分词器

IK提供了两个分词算法:ik_smart和ik_max_word,其中ik_smart为最少切分,ik_max_word为最细粒度划分

下载地址:https://github.com/medcl/elasticsearch-analysis-ik/releases

  1. 下载之后放入ElasticSearch安装目录下的插件目录即可(Plugins)

    需要新建文件夹,将文件解压到文件夹中。 文件夹名称建议使用ik

  2. 重启ElasticSearch,可以看到ik分词器已经被加载了

    image-20211015155404277

    如果不确定是否加载了ik分词器插件,可以通过bin目录下执行cmd命令窗口,elasticsearch-plugin list 命令进行查询插件列表

image-20211015155901285

​ 3.启动Kibana,进行查询测试 也可以使用其他的工具 例如:Postman等测试工具

ik_smart最少切分

image-20211015163847146

ik_max_word最细粒度划分,也就是说将一段文字尽可能拆分成多段的,直到没有分词的可能性

image-20211015164148762

自定义字典:

当我们发现某些词不能被拆分,但是还是被ik分词器进行了拆分,例如:你好我叫123 被分为:你好、我、叫、1、2、3

如何让分词器不去拆分某些词呢。这个时候我们就需要向分词器的字典中添加词组

例:

image-20211015165516129

向ik分词器字典中添加词组

打开ik分词器配置文件夹(config) , 编辑IKAnalyzer.cfg.xml文件 *.dic文件都是它的词典

image-20211015170030934

新建我们自己的词典 文件xxx.dic,新建完成后,将文件名.dir加入 key为ext_dict标签内

文件内应该写入想要组词的文字,这里就写撸森了,因为需要让ik分词器识别它为一个词

image-20211015170626117

重启 ElasticSearch!!!

再次测试一波!

添加词典前 和 添加词典后

image-20211015170938325

以后需要添加词组的话只需要在自定义.dic字典文件中添加一个词组即可!

RestFul风格

一种软件架构风格,而不是标准,只是提供了一组设计原则和约束条件。它主要用于客户端和服务器交互类的软件。基于这个风格设计的软件可以更简洁,更有层次,更易于实现缓存机制。

基本Rest命令说明:

methodurl地址描述
PUTlocalhost:9200/索引名称/类型名称/文档id创建文档(指定文档id)
POSTlocalhost:9200/索引名称/类型名称创建文档(随机文档id)
POSTlocalhost:9200/索引名称/类型名称/文档id/_update修改文档
DELETElocalhost:9200/索引名称/类型名称/文档id删除文档
GETlocalhost:9200/索引名称/类型名称/文档id通过文档id查询文档
POSTlocalhost:9200/索引名称/类型名称/_search查询所有数据

字段类型

默认情况下不指定类型,ElasticSearch将会自动配置字段类型

类型
字符串类型text、keyword
数值类型long、integer、short、byte、double、float、half float、scaled float
日期类型date
布尔类型boolean
二进制类型binary

创建索引时建立类型规则

PUT /test2
{
  "mappings": {
    "properties": {
      "name":{
        "type": "text"
      },
      "age":{
        "type": "integer"
      },
      "time":{
        "type": "date"
      }
    }
  }
}

可以通过GET命令进行获得指定 索引、以及文档信息 例:GET /test1

image-20211016172413013

扩展命令

通过GET /_cat 可以获取ES的信息

image-20211016173329670

索引基本操作

创建索引

PUT /索引名/类型名/文档id
{请求体}

image-20211016163328328

image-20211016163826676

更新数据

方式1:直接 进行覆盖文档

方式2:使用 POST /索引/类型/文档id/_update进行更新

方式1:

image-20211016174419567

方式2:

image-20211016175004773

删除操作

通过DELETE命令进行删除 索引、文档

例:DELETE /test1、DELETE /test1/_doc/1

根据你的请求来判断是删除索引还是删除文档

文档基本操作

基本操作

  1. 添加数据

    PUT /xiaoge/user/1
    {
      "name":"张三",
      "age":20,
      "desc":"你好啊",
      "tags":["直男","技术宅"]
    }
    

    image-20211016181927281

  2. 获取数据

    image-20211016182512441

  3. 更新数据 使用PUT 或者 POST /xxx/xx/id/_update (传递参数需要在doc对象内传递) 【推荐使用update】

简单的条件查询,可以根据默认的映射规则,产生基本查询!

image-20211016184308087

复杂操作搜索 (排序、分页、高亮、模糊查询、精准查询)

image-20211016190321227

#精确匹配
GET /xiaoge/user/_search
{
  "query":{
    "match": {
      "name": "张三"
    }
  }
}

指定显示某个字段信息

image-20211017103402961

排序操作

image-20211017103841507

分页操作

image-20211017104248868

布尔值查询

must(and),所有条件都需要符合

image-20211017110029263

should(or)满足一个即可

image-20211017110550084

must_not (不需要的)

image-20211017110823491

过滤数据 filter ,可以取区间值,也可以单判断

image-20211017111706295

匹配多个条件

image-20211017112732264

精确查询

term 查询是直接通过倒排索引指定的词条进行精确查询, 查询的时候可以通过字段.keyword进行直接直接查询

关于分词

  • term:直接查询精确的
  • match:会先通过分词器解析 (先分析,后查询)

两个类型 text keyword

  • text:会被分词器拆分
  • keyword : 不会被分词器进行拆分

精确查询多个值

image-20211017121025499

高亮查询

GET /xiaoge/user/_search
{
  "query":{
    "match": {
      "name": "张三"
    }
  },
  "highlight":{
    "fields": {
      "name": {}
    }
  }
}

image-20211017124337640

默认情况下是em标签进行包裹,如何自定义标签呢?通过pre_tags 和 post_tags 设置前缀和后缀标签内容

GET /xiaoge/user/_search
{
  "query":{
    "match": {
      "name": "张三"
    }
  },
  "highlight":{
    "pre_tags": "<p style='color:red'>",
    "post_tags": "</p>", 
    "fields": {
      "name": {}
    }
  }
}

image-20211017125356585

集成SpringBoot

image-20211017133743595

image-20211017133758620
image-20211017153040734
高版本文档地址:https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high.html

  1. 添加依赖

    注意:由于SpringBoot默认整合版本不是我们需要的版本,因此需要修改依赖的版本信息为当前elasticsearch对应的版本。

    <!-- SpringBoot与elasticsearch整合的相关依赖 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
    <!--修改ElasticSearch版本信息-->
    <properties>
        <java.version>1.8</java.version>
        <elasticsearch.version>7.15.1</elasticsearch.version>
    </properties>
    <!--
    因为SpringBoot默认已经整合了所以我们只需要改下默认版本即可
    <dependency>
        <groupId>org.elasticsearch.client</groupId>
        <artifactId>elasticsearch-rest-high-level-client</artifactId>
        <version>7.15.1</version>
    </dependency>
    -->
    

    image-20211017154146956

  2. 初始化

    @Configuration
    public class ElasticSeachConfig {
        @Bean
        public RestHighLevelClient restHighLevelClient() {
            RestHighLevelClient client = new RestHighLevelClient(
                    RestClient.builder(
                            new HttpHost("127.0.0.1", 9200, "http")
                            /* 多个节点也是在当前地方配置 */
                            //, new HttpHost("localhost", 9300, "http")
                    ));
            return client;
        }
    }
    

索引API操作

  1. 创建索引

    //创建索引请求
    CreateIndexRequest request = new CreateIndexRequest("xiaoge_index");
    //执行创建请求
    //客户端执行请求,获得响应
    CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
    System.out.println(createIndexResponse);
    
  2. 获取索引是否存在

    //获取索引 只能判断是否存在
    GetIndexRequest request = new GetIndexRequest("xiaoge_index");
    boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
    System.out.println(exists);
    
  3. 删除索引

    //删除索引
    DeleteIndexRequest request = new DeleteIndexRequest("xiaoge_index");
    //返回响应结果
    AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
    System.out.println(response.isAcknowledged());
    

文档API操作

  1. 添加文档

    //创建对象
    User user = new User();
    user.setName("小王");
    user.setAge(15);
    //创建请求
    IndexRequest request = new IndexRequest("xiaoge_index");
    //创建规则 PUT /xiaoge_index/doc/1
    request.id("1");//设置ID
    request.timeout("1s");//设置超时时间
    //将我们的数据放入请求
    request.source(JSON.toJSONString(user), XContentType.JSON);
    
    //客户端发送请求,获取响应结果
    IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
    System.out.println(indexResponse.toString());
    //返回状态
    System.out.println(indexResponse.status());
    
  2. 获取文档是否存在

    GetRequest getRequest = new GetRequest("xiaoge_index", "1");
    //设置后将不会返回_source的上下文 提升效率
    getRequest.fetchSourceContext(new FetchSourceContext(false));
    //排序规则
    getRequest.storedFields("_none_");
    //判断索引和文档是否存在
    boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
    
  3. 获取文档信息

    GetRequest getRequest = new GetRequest("xiaoge_index", "1");
    //客户端发送请求,返回响应结果
    GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
    //获取文档内容
    System.out.println(getResponse.getSourceAsString());
    //返回文档所有信息 跟命令测试一样
    System.out.println(getResponse);
    
  4. 更新文档内容

    //创建更新请求
    UpdateRequest updateRequest = new UpdateRequest("xiaoge_index","1");
    //超时时间
    updateRequest.timeout("1s");
    //更新数据放入请求中
    updateRequest.doc(JSON.toJSONString(new User("小白",12)),XContentType.JSON);
    //客户端发送请求,返回响应结果
    UpdateResponse update = client.update(updateRequest, RequestOptions.DEFAULT);
    System.out.println(update);
    
  5. 删除文档

    //创建删除请求
    DeleteRequest deleteRequest = new DeleteRequest("xiaoge_index", "1");
    //超时时间
    deleteRequest.timeout("1s");
    //客户端发起请求,返回响应数据
    DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
    System.out.println(deleteResponse);
    
  6. 批量插入数据

    批量更新、删除操作都可以在bulkRequest.add方法里面创建不同请求进行操作!

    //批量插入数据
    BulkRequest bulkRequest = new BulkRequest();
    
    //创建集合
    ArrayList<User> users = new ArrayList<>();
    users.add(new User("小明",12));
    users.add(new User("小白",20));
    users.add(new User("小黑",20));
    users.add(new User("小桥",15));
    users.add(new User("小灰",10));
    
    //循环向bulkRequest中添加请求
    for(int i=0;i<users.size();i++){
        //在这里可以通过add方法添加不同请求进行 删除、更新操作
        bulkRequest.add(
            new IndexRequest("xiaoge_index")
            .id(""+(i+1))
            .source(JSON.toJSONString(users.get(i)),XContentType.JSON)
        );
    }
    
    //客户端发起请求,返回响应数据
    BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);
    //返回插入结果是否失败 false代表成功
    System.out.println(bulkResponse.hasFailures());
    
  7. 根据条件查询文档信息

    通过QueryBuilders可以快速创建查询条件!

    //创建查询请求对象
    SearchRequest searchRequest = new SearchRequest("xiaoge_index");
    //构建搜索条件
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    //查询所有 QueryBuilders
    //精确查询 termQuery
    // xxx
    MatchAllQueryBuilder queryAll = QueryBuilders.matchAllQuery();
    //开始下标
    sourceBuilder.from(1);
    //结束下标
    sourceBuilder.size(5);
    sourceBuilder.query(queryAll);
    //查询超时时间
    sourceBuilder.timeout(new TimeValue(60,TimeUnit.SECONDS));
    //高亮显示
     HighlightBuilder highlightBuilder = new HighlightBuilder();
    highlightBuilder.field("name");
    highlightBuilder.preTags("<li style='color:red;font-weight:bold'>");
    highlightBuilder.postTags("</li>");
    sourceBuilder.highlighter(highlightBuilder);
    //将构建条件放入请求中
    searchRequest.source(sourceBuilder);
    
    //客户端发送请求,响应数据
    SearchResponse search = client.search(searchRequest, RequestOptions.DEFAULT);
    
    //返回的所有结果都存在hits中
    SearchHits hits = search.getHits();
    for (SearchHit hit : hits) {
        System.out.println(hit);
    }
    

    高亮查询关键代码

    		SearchRequest searchRequest = new SearchRequest("goods_jd");
            SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
            //分页操作
            sourceBuilder.from((index-1)*size);
            sourceBuilder.size(size);
            //查询操作 不传入关键字的话默认查询前30条数据
            if(keyword!=null && keyword.trim().length()>0){
                sourceBuilder.query(QueryBuilders.matchPhraseQuery("title",keyword));
            }else{
                sourceBuilder.query(QueryBuilders.matchAllQuery());
            }
            sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
            //高亮配置   ----从这里开始----
            HighlightBuilder highlightBuilder = new HighlightBuilder();
            highlightBuilder.field("title");
            highlightBuilder.preTags("<span style='color:red'>");
            highlightBuilder.postTags("</span>");
            sourceBuilder.highlighter(highlightBuilder);
    
            searchRequest.source(sourceBuilder);
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            SearchHits hits = searchResponse.getHits();
            //用于存储数据
            ArrayList<Map<String,Object>> list = new ArrayList<>();
            //遍历第二层hits
            for (SearchHit hit : hits.getHits()) {
                //获取hit中的数据 这里的数据就是我们要的数据
                Map<String, Object> sourceAsMap = hit.getSourceAsMap();
                //获取当前高亮字段
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                //获取指定高亮字段 如果没有进行匹配查询那么这里就是null
                HighlightField title = highlightFields.get("title");
                //如果存在高亮
                if(title!=null){
                    Text[] fragments = title.getFragments();
                    String n_title = "";
                    //将分段的字符串进行拼接,然后去把原来sourceAsMap中的title字段进行置换
                    for (Text fragment : fragments) {
                        n_title += fragment;
                    }
                    sourceAsMap.put("title",n_title);
                }
                //最后添加到list中
                list.add(sourceAsMap);
            }
            return list;
    

    这里暂时还没有使用IK分词器

爬坑

image-20211019170943782

参考文献

狂神说Java

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值