学习资料:狂神说

ElactisSearch 7.6.2

ElasticSearch

分布式搜索引擎

1. 概述

1.1 ELK

ELK是ElasticSearch、Logstash、Kibana三大开源架构首字母大写简称,市面上也被称为Elastic Etack。

  • ElasticSearch是以RESTful方式进行近实时地搜索平台框架,提供存储和搜索;

  • Logstash是ELK的中央数据流引擎,用于从不同目标(文件、数据存储、mq)收集不同格式的数据,经过过滤然后输出到不同的目的地(文件、mq、redis、ElasticSearch、kafka等);

  • Kibana可以将ElasticSearch的数据通过友好的页面展示出来,实现实时分析功能。

1.2 ElasticSearch 简介

elasticsearch 作者:Shay Banon,简称es

es是一个开源的高扩展的分布式全文检索引擎,它可以近乎实时的存储、检索数据。本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。

es是使用java开发,基于lucene来实现素有索引和搜索的功能,但是它的目的是通过简单的RESTful API来隐藏Lucene的复杂性,从而让全文检索变得更简单。

根据国际权威的数据库产品测评机构DB Engines的统计,在2016年1月,ElasticSearch一超过Solr等,成为排名第一的搜索引擎类应用。

1.3 Solr简介

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

Solr可以独立运行在Jetty、Tomcat等Servlet容器中。

  • 通过Post请求向Solr服务器发送一个描述Field及其内容的XML文档,Solr根据xml文档进行添加、删除、修改操作。
  • 通过Get请求对Solr发起搜索,返回Xml、Json等格式的查询结果进行解析,组织页面布局。

1.4 Lucene简介

Lucene是一套信息检索工具包,索引结构,读写索引的工具、排序,搜索规则。不包含搜索引擎。

在java开发环境中,Lucene是一个成熟的免费开源工具。

1.5 ElasticSearch VS Solr

  • 对已存在的数据进行检索:es < solr
  • 对数据添加索引:es > solr
  • 随着数据量增大,查询性能:es > solr
  1. es自带分布式协调管理功能,solr需要zookeeper进行分布式管理;
  2. es仅支持json,solr支持json、xml、csv等;

1.6 Kibana简介

Kibana是一个针对ElasticSearch的开源分析及可视化平台,用来搜索、查看交互存储在ElasticSearch索引中的数据。 使用Kibana ,
可以通过各种图表进行高级数据分析及展示。Kibana让海量数据更容易理解。它操作简单,基于浏览器的用户界面可以快速创建仪
表板( dashboard )实时显示ElasticSearch查询动态。

官网:http://www.elastic.co/cn/kibana

2. ElasticSearch环境

官网地址:https://www.elastic.co/products/elasticsearch

2.1 ElasticSearch 下载、解压、运行

es windows版 7.6.2 下载链接

ps:es需要jdk1.8以上版本

下载解压后目录结构:

bin #启动关闭等批处理
config #配置文件elasticsearch.yml   #ed的配置文件,默认9200端口,跨域等配置log4j2 #日志配置文件jvm.options  #java虚拟机相关配置
jdk #运行环境
lib #相关jar包
modules #功能模块
plugins #插件

启动:

启动bin目录下的 elasticsearch.bat

启动完成:

2.2 ElasticSearch head 下载、安装、运行

es head 是一个es的可视化工具

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

下载解压后,在elasticsearch-head-master目录下运行cmd,下载相关依赖

npm install

因为外网下载很慢,这里附加安装cnpm的方法:

  1. 先安装cpnm
npm install -g cnpm -registry=https://registry.npm.taobao.org
  1. 安装自动配置好环境变量,直接使用cnpm -v版本。如果没有配置环境变脸可以百度跟着修改环境变量即可。

安装完依赖后,在head目录启动

npm run start

配置es可跨域访问:

找到es/config/elasticsearch.yml。在末尾添加一下配置,表示开启跨域访问,匹配任何地址

http.cors.enabled: true
http.cors.allow-origin: '*'

改完,重新启动es

es启动完成后,回到es head点击[链接]按钮

新建索引:

可以把“索引”当作数据库来理解。

创建了一个 ssx 的索引,在 “ 数据浏览” 可以查看该索引的数据。

2.3 Kibana下载、安装、运行

kibana windows版 7.6.2 下载地址

  1. 下载解压

  2. 下载依赖

    在kibana目录下执行

    cnpm install
    
  3. 启动

    启动bin目录下 kibana.bat

  1. 使用kibana国际化语言包汉化

    ...kibana目录\x-pack\plugins\translations\translations\zh-CN.json
    

    这里可以看到有中文翻译

    打开kibana配置文件 \config\kibana.yml

    在最后面加上:

    i18n.locale: "zh-CN"
    

    修改配置后需要重启kibana

3. ES 核心概念

初步认识后,搭建好es环境,就开始深入了解es的核心概念了。

elasticSearch是面向文档的数据库。

一切都是JSON!

Relational DataBase ElasticSearch
数据库(database) 索引(indices)
表(tables) types:用的比较少,将来可能会淘汰。
行(rows):数据 documents
字段(columns) fields

3.1 物理设计:

ES在后台把每个索引划分成多个分片,每份分片可以在集群中的不同服务器之间迁移。

es一个服务就是一个集群,默认集群名称:easticsearch。

3.2 逻辑设计:

一个索引中包含多个文档。

3.2.1 文档

文档就好比关系型数据库中的一条一条记录

tb_user
1   ssx     18
2   jaychow  23

es是面向文档的,也就是搜索的最小单位是文档。

es中的文档的重要属性:

  • 自我包含:一片文档同事包含字段和对应的值,也就是同时包含key:value;
  • 层次型:一个文档中包含自文档,可以形成复杂的逻辑实体;
  • 灵活的结构:文档不依赖预先定义的模式,意思是不需要提前确定好字段信息,动态的添加字段。

尽管可以随意新增或忽略某个字段,但每个字段的类型非常重要,比如年龄字段可以是整型也可以是字符。es会保存字段和类型之间的映射及其他的设置,这种映射具体到每个映射的各种类型,所以es中类型有时候又叫映射类型。

3.2.2 类型

数据类型

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

文档是无模式的,新增一个字段时,es会自动匹配一个类型,但这种匹配是不准确的。所以一般都会定义好这个字段的类型,以杜绝不必要的麻烦。

3.2.3 索引

数据库

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

节点和分片:

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

上图是一个es集群,有3个节点。

以P为例,P0为主分片,其它P1、P2都不在同一个节点上。实现了es高可用集群。

实际上一个分片是一个Lucene索引,一个包含倒排索引的文件目录,倒排索引的结构使得es在不扫面全部文档的情况下,就能实现关键字搜索。

倒排索引:

es使用的是一种成为倒排索引的结构,采用Lucene倒排索引作为底层支持。这种结构适用于快速的全文搜索。

一个索引由文档中所有不重复的列构成,对于每一个词都有一个包含它的文档列表。

需要创建倒排索引,首先将每个文档拆分成独立的词(词条、tokens),然后创建一个不重复的的排序的词条列表,里面列出每个词条出现在哪个文档。

个人理解:这种倒排索引的意思,不是将123=>321的顺序倒排,而是逻辑的反转。普通索引就是ID做一个主键索引,然后根据这个创建好B+Tree索引,而这个倒排索引是将内容(词)抽出来,反向地将记录再排一遍构成倒排索引!

示例:

那么这么做的好处是,当来一个关键字的时候,先在倒排索引中,找到哪些文档有这个关键字,直接去对应文档中再找,规避了全库全文档的索引,是一种优化手段。

在es中,索引被分成了多个分片,每份分片是一个Lucene的索引。所以说es索引是由多个Lucene索引组成。所以一般说索引指的是es的索引。只是es索引的底层聚合了Lucene的索引。

4. IK 分词器

分词就是把一段词,分开成多个字。

而中文的分词,一般是把一段词分称一个一个词语:美丽的一天 -> 美丽、的、一天。

然后针对中文分词的插件:ik分词器。

ik分词器提供了两个分词算法:

  • ik_smart:最少切分
  • ik_max_word:最细粒度切分

4.1 安装

github

7.6.2 下载地址

下载、解压、放入es的plugins目录中,重启es

使用elasticsearch-plugin查看加载的插件

4.2 测试

使用kibana测试两种分词算法

4.2.1 ik_smart

最少切分算法

进行最简短的拆分并且没有重复的词

如果对:“石似心”进行拆分,会被拆成三个字,属于自造词,原本并不存在。这种自造词需要加入词库。

4.2.2 ik_max_word

最细粒算法

4.3 配置自定义词库

来到ik分词器的配置文件夹 config

里面有很多dic格式的文件,这些都是默认的词库。

  1. 创建一个文件:ssx.dic

  2. 里面写入:石似心

  3. 找到ik分词器的配置文件

...\plugins\elasticsearch-analysis-ik-7.6.2\config\IKAnalyzer.cfg.xml
  1. 将自定义的词库文件引入

  1. 重启es

  2. 再次使用ik_smart拆分“石似心”

被判定为一个词

5. Rest风格操作ES

发送请求操作es的数据

Method url 说明
PUT localhost:9200/索引名称/类型名称/文档ID 创建文档,指定文档ID
POST localhost:9200/索引名称/类型名称 创建文档,随机文档ID
POST /索引名称/类型名称/文档ID/_update 修改文档
DELETE /索引名称/类型名称/文档ID 删除文档
GET /索引名称/类型名称/文档ID 通过文档ID查询文档
POST /索引名称/类型名称/_search 查询所有数据

在kibana上使用Rest风格的语句操作es

5.1 PUT

5.1.1 PUT /索引名称/类型名称/文档ID

指定索引、类型、文档

PUT /test01/type01/doc01
{"name":"石似心","money":100
}

返回值:

#! Deprecation: [types removal] Specifying types in document index requests is deprecated, use the typeless endpoints instead (/{index}/_doc/{id}, /{index}/_doc, or /{index}/_create/{id}).
{"_index" : "test01",  //索引名称"_type" : "type01",    //类型名称"_id" : "doc01",      //文档id"_version" : 1,     //版本1"result" : "created",  //索引状态"_shards" : {           //分片信息"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1
}

5.1.2 创建索引规则

创建索引规则(指定属性对应的类型)

PUT /索引名称

PUT /test02
{"mappings": {"properties": {"name": {            //属性"type": "text"  //类型},"age": {            //属性"type": "long"  //类型},"birthday": {       //属性"type": "date"  //类型}}}
}

返回值:

{"acknowledged" : true,"shards_acknowledged" : true,"index" : "test02"
}

查看test02:

GET test02

查看索引:test02的属性

{"test02" : {"aliases" : { },"mappings" : {"properties" : {"age" : {"type" : "long"},"birthday" : {"type" : "date"},"name" : {"type" : "text"}}},"settings" : {"index" : {"creation_date" : "1602658651489","number_of_shards" : "1","number_of_replicas" : "1","uuid" : "nn-fPvRGSfqqqXVsNQGglw","version" : {"created" : "7060299"},"provided_name" : "test02"}}}
}

5.1.3 PUT /索引/_doc/文档

不指定类型创建索引和文档

PUT /test03/_doc/001
{"name":"高山低谷"
}

返回值:

{"_index" : "test03","_type" : "_doc","_id" : "001","_version" : 1,"result" : "created","_shards" : {"total" : 2,"successful" : 1,"failed" : 0},"_seq_no" : 0,"_primary_term" : 1
}

查看test03中的name的数据类型:

GET test03

返回值:(es自动配置的类型)

5.1.4 PUT 实现修改

覆盖式的修改,会将原来的001中的属性直接全部替换为新的值

PUT /test03/_doc/001
{"age":"2"
}

返回值:

{"_index" : "test03","_type" : "_doc","_id" : "001","_version" : 2,"_seq_no" : 3,"_primary_term" : 1,"found" : true,"_source" : {      //已经没有name属性"age" : "2"}
}

5.2 POST

5.2.1 _update实现指定属性修改

当一个文档中有多个属性时,一般只是需要修改某个属性,而不影响其它属性。

POST /test03/_doc/001/_update
{"doc": {"name": "晴天"}
}

查看test03:

{"_index" : "test03","_type" : "_doc","_id" : "001","_version" : 10,"_seq_no" : 9,"_primary_term" : 1,"found" : true,"_source" : {"name" : "晴天","age" : "3"}
}

只有name属性修改了。

5.3 DELETE 删除索引

DELETE test01

返回值:

{"acknowledged" : true
}

5.4 GET 时间简单查询

GET test03/_doc/_search?q=name:晴天

返回结果:

  1. 5 _cat 命令

5.5.1 查看ES健康状态

GET _cat/health

返回值:

1602660039 07:20:39 elasticsearch yellow 1 1 11 11 0 0 8 0 - 57.9%

5.5.2 查看索引的状态

GET _cat/indices

返回值:

yellow open test03                   DvMoFyzxRi60IgrqaGGowA 1 1  1 2 11.7kb 11.7kb
yellow open test02                   nn-fPvRGSfqqqXVsNQGglw 1 1  0 0   283b   283b
yellow open test01                   mYAGuQCqRLe9TeJpZDl_LA 1 1  1 0  3.7kb  3.7kb
green  open .kibana_task_manager_1   N-2MnNffTp6L3uweAK-GZw 1 0  2 0 12.3kb 12.3kb
green  open .apm-agent-configuration fz-TKC2tQ82UJ3z6NX8BEg 1 0  0 0   283b   283b
yellow open ssx                      sBLSKchzSROHqEnOXuC94g 5 1  0 0  1.3kb  1.3kb
green  open .kibana_1                -HhBXxQtRMqLdYSzKzIvqA 1 0 14 5 58.4kb 58.4kb

6. 复杂查询语法

排序、分页、高亮、模糊…

准备了一些数据:

6.1 基础查询

GET test03/_search
{"query":{"match":{"name":"晴天"}}
}

返回结果:

6.2 结果过滤

“_source”: [“name”]

限制返回值只有name

GET test03/_doc/_search
{"query":{"match":{"name":"晴天"}},"_source": ["name"]
}

6.3 排序

sort

我测试的时候排text类型的属性会报错,估计只能排一些有排序逻辑的类型:long、date…

GET test03/_search
{"query":{"match":{"name":"晴天"}},"_source": ["name","birthday"],"sort": [{"birthday": {"order": "asc"}}]
}

返回结果:

可以看到,排序之后的_score 分值直接返回null。

6.4 分页

from:从第几条数据开始

size:获取多少条数据

GET test03/_search
{"query":{"match":{"name":"晴天"}},"_source": ["name","birthday"],"sort": [{"birthday": {"order": "asc"}}],"from":0,"size":1
}

返回结果:

6.5 布尔查询

多条件筛选、匹配或不匹配筛选:

must、must_not......

must:全部匹配(and)

should:可能 (or)

must_not:不匹配(not、不等于)

GET test03/_search
{"query":{"bool": {"must": [{"match": {"name": "晴天"}},{"match": {"age": "3"}}]}}
}

6.6 过滤器

filter

区间过滤

  • gt >
  • gte >=
  • lt <
  • lte <=

需求生日在:2020-01-08~2020-03-03之间

GET test03/_search
{"query":{"bool": {"must": [{"match": {"name": "晴天"}}],"filter": [{"range": {"birthday": {"gte": "2020-01-08","lte": "2020-03-03"}}}]}}
}

6.7 精确查询

match:使用分词器进行解析

term:查询直接通过倒排索引指定的词条进行精确查找。

验证:

创建test4索引,配置索引映射类型。

keyword是不可拆分的类型。

PUT test04
{"mappings": {"properties": {"name_k": {"type": "keyword"},"name_t": {"type": "text"}}}
}

数据

PUT test04/_doc/1
{"name_k": "石似心","name_t": "石似心"
}PUT test04/_doc/2
{"name_k": "石似心2","name_t": "石似心2"
}

使用分词器查询:

GET _analyze
{"analyzer": "keyword","text": "石似心"
}

使用分词器返回值:

{"tokens" : [{"token" : "石似心","start_offset" : 0,"end_offset" : 3,"type" : "word","position" : 0}]
}

使用默认的分词查询:

GET _analyze
{"analyzer": "standard","text": "石似心"
}

使用默认的分词返回值:(被解析为单个词)

{"tokens" : [{"token" : "石","start_offset" : 0,"end_offset" : 1,"type" : "<IDEOGRAPHIC>","position" : 0},{"token" : "似","start_offset" : 1,"end_offset" : 2,"type" : "<IDEOGRAPHIC>","position" : 1},{"token" : "心","start_offset" : 2,"end_offset" : 3,"type" : "<IDEOGRAPHIC>","position" : 2}]
}

多个值的精确查询:

精确查询“name_k”等于“石似心2”或者“石似心”

GET test04/_search
{"query":{"bool": {"should": [{"term": {"name_k": "石似心2"}},{"term": {"name_k": "石似心"}} ]}}
}

6.9 高亮

指定属性进行高亮

GET test04/_search
{"query":{"bool": {"should": [{"term": {"name_k": "石似心2"}}]}},"highlight": {"pre_tags": "<p style='font-color:red;'>","post_tags": "</p>", "fields": {"name_k": {}}}
}

返回值:

7. 集成SpringBoot

7.1 springboot与es

  1. 引入依赖

    <properties>                  <elasticsearch.version>7.6.2</elasticsearch.version>
    </properties><dependencies><dependency>  <groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-elasticsearch</artifactId></dependency>......
    
  2. 配置客户端bean

    import org.apache.http.HttpHost;
    import org.elasticsearch.client.RestClient;
    import org.elasticsearch.client.RestHighLevelClient;
    import org.springframework.beans.factory.annotation.Configurable;
    import org.springframework.context.annotation.Bean;/*** es配置类,注入客户端bean*/
    @Configurable
    public class ElasticSearchConfig {@Beanpublic RestHighLevelClient restHighLevelClient(){/*** 配置集群地址*/RestHighLevelClient client = new RestHighLevelClient(RestClient.builder(new HttpHost("127.0.0.1",9200,"http")));return client;}
    }
    

es的配置还有一些,官网好像也没看到有完整的配置信息说明,但是根据狂神的介绍找到springboot的自动配置类,可以了解到比较完整的es配置。

自动配置源码:

package org.springframework.boot.autoconfigure.elasticsearch;import org.elasticsearch.client.RestClient;import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;/*** {@link EnableAutoConfiguration Auto-configuration} for Elasticsearch REST clients.** @author Brian Clozel* @author Stephane Nicoll* @since 2.1.0*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnClass(RestClient.class)
@EnableConfigurationProperties(ElasticsearchRestClientProperties.class)
@Import({ ElasticsearchRestClientConfigurations.RestClientBuilderConfiguration.class,ElasticsearchRestClientConfigurations.RestHighLevelClientConfiguration.class,ElasticsearchRestClientConfigurations.RestClientFallbackConfiguration.class })
public class ElasticsearchRestClientAutoConfiguration {}

里面主要是引入三个内部类进行了一些配置:

@Import({ ElasticsearchRestClientConfigurations.RestClientBuilderConfiguration.class,ElasticsearchRestClientConfigurations.RestHighLevelClientConfiguration.class,ElasticsearchRestClientConfigurations.RestClientFallbackConfiguration.class })

以后再去深入研究,循序渐进,现在先把es全面认识完。

7.2 api操作es索引

测试三条api

@SpringBootTest
class AEsApiApplicationTests {@Autowiredprivate RestHighLevelClient restHighLevelClient;/*** 测试创建索引*/@Testvoid testCreateIndex() throws IOException {//创建 “创建索引”的 http 请求CreateIndexRequest testCreateIndex = new CreateIndexRequest("test_api_index");// 使用客户端.索引操作.创建,传入“创建索引”的请求,使用默认参数CreateIndexResponse createIndexResponse =restHighLevelClient.indices().create(testCreateIndex, RequestOptions.DEFAULT);//返回创建的索引名称System.out.println(createIndexResponse.index());}/*** 测试获取索引*/@Testvoid testGetIndex() throws IOException {//创建 “获取索引”的 http 请求GetIndexRequest getIndexRequest = new GetIndexRequest("test_api_index");// 使用客户端.索引操作.获取,传入“获取索引”的请求,使用默认参数GetIndexResponse getIndexResponse =  restHighLevelClient.indices().get(getIndexRequest, RequestOptions.DEFAULT);Arrays.stream(getIndexResponse.getIndices()).forEach(System.out::println);}/*** 测试删除索引*/@Testvoid testDeleteIndex() throws IOException {//创建 “获取索引”的 http 请求DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("test_api_index");// 使用客户端.索引操作.获取,传入“获取索引”的请求,使用默认参数AcknowledgedResponse delete = restHighLevelClient.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);System.out.println(delete.isAcknowledged());}}

7.3 api操作es文档

7.3.1 创建文档

    /*** 测试创建文档*/@Testvoid testAddDocument() throws IOException{//实体类User user = new User("石似心",18);//创建请求,指定关联的索引IndexRequest indexRequest = new IndexRequest("test_api_index");//设置相关配置//PUT /test_api_index/_doc/001indexRequest.id("001");indexRequest.timeout("1s");//实体类数据放入请求indexRequest.source(JSON.toJSONString(user), XContentType.JSON);//使用es客户端将请求发送出去,返回响应IndexResponse indexResponse = restHighLevelClient.index(indexRequest, RequestOptions.DEFAULT);System.out.println(indexResponse.toString());System.out.println(indexResponse.status());}

console

IndexResponse[index=test_api_index,type=_doc,id=001,version=1,result=created,seqNo=0,primaryTerm=1,shards={"total":2,"successful":1,"failed":0}]
CREATED

7.3.2 获取文档

    /*** 测试判断指定文档是否存在*/@Testvoid testExistsDocument() throws  IOException{//创建GET请求GetRequest getRequest = new GetRequest("test_api_index","001");//不获取返回的  _sourcegetRequest.fetchSourceContext(new FetchSourceContext(false));getRequest.storedFields("_none_");boolean exists = restHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);System.out.println(exists);}/*** 测试获取对应文档*/@Testvoid testGetDocument() throws IOException{//创建GET请求GetRequest getRequest = new GetRequest("test_api_index","001");//访问GetResponse getResponse = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);System.out.println(getResponse.getSourceAsString());System.out.println(getResponse);}

console

{"age":18,"name":"石似心"}
{"_index":"test_api_index","_type":"_doc","_id":"001","_version":1,"_seq_no":0,"_primary_term":1,"found":true,"_source":{"age":18,"name":"石似心"}}

7.3.3 修改文档

    /*** 测试修改对应文档*/@Testvoid testUpdateDocument() throws IOException{UpdateRequest updateRequest = new UpdateRequest("test_api_index", "001");updateRequest.timeout(TimeValue.timeValueSeconds(1));//新的user,填入更新请求,说明传入的是JSON类型的数据User user = new User("给未来的自己",30);updateRequest.doc(JSON.toJSONString(user),XContentType.JSON);//提交请求UpdateResponse update = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);System.out.println(update.status());}

7.3.4 批量增加文档

bulk

    /*** 测试批量添加文档*/@Testvoid testBulkAddDocument() throws IOException{//批量处理请求BulkRequest bulkRequest = new BulkRequest();List<User> userList = new ArrayList<User>(){{add(new User("多想爱这个世界啊",12));add(new User("如果有一天",22));add(new User("我不曾爱过你",32));add(new User("你是否知道",42));add(new User("我自己骗自己",52));}};//将用户填入IndexRequest,在填入BulkRequestAtomicInteger i = new AtomicInteger(0);userList.forEach(u->{i.incrementAndGet();bulkRequest.add(// 批量新增、批量删除、批量修改.....new IndexRequest("ssx").id(i.toString()).source(JSON.toJSONString(u), XContentType.JSON));});//发送请求BulkResponse bulk = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);System.out.println(bulk.status());System.out.println(bulk.hasFailures());//失败数}

7.3.5 查询

查询中使用了很多各种各样的builder。

/*** 测试查询*/
@Test
void testSearch() throws IOException{//查询请求SearchRequest searchRequest = new SearchRequest("ssx");//构建查询的内容SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();sourceBuilder.timeout(new TimeValue(1, TimeUnit.SECONDS));/** 使用QueryBuilders组装查询条件* QueryBuilders.matchQuery()* QueryBuilders.termQuery() //精确查找*/TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("age", 12);sourceBuilder.query(termQueryBuilder);//将拼装好的查询条件放入查询请求searchRequest.source(sourceBuilder);//发送查询请求SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);System.out.println(JSON.toJSONString(search.getHits()));//打印结果for (SearchHit hit : search.getHits().getHits()) {System.out.println(hit.getSourceAsMap());}
}

8. 实战

创建一个新项目,导入狂神整理的静态页面。

模拟京东的搜索,仅做学习用。

8.1 准备数据

jsoup爬取30条京东搜索页的数据做学习用。

8.2 实现查询逻辑

    /*** 查询数据*/public List<Map<String,Object>> searchData(String keywords,int page,int pageSize) throws IOException {SearchRequest searchRequest = new SearchRequest("jd_goods");SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("name", keywords);TermQueryBuilder queryBuilder = QueryBuilders.termQuery("name", keywords);sourceBuilder.query(queryBuilder);sourceBuilder.timeout(TimeValue.timeValueSeconds(10));sourceBuilder.from(page);sourceBuilder.size(pageSize);searchRequest.source(sourceBuilder);//高亮设置HighlightBuilder highlightBuilder = new HighlightBuilder();highlightBuilder.preTags("<span style='color:red'>");highlightBuilder.postTags("</span>");highlightBuilder.field("name");sourceBuilder.highlighter(highlightBuilder);//应用高亮设置SearchResponse search = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);System.out.println(searchRequest.toString());List<Map<String,Object>> goodsList = new ArrayList<>();Arrays.stream(search.getHits().getHits()).forEach(g->{Map<String, Object> sourceAsMap = g.getSourceAsMap();goodsList.add(sourceAsMap);//处理高亮字段HighlightField highlightField = g.getHighlightFields().get("name");if(highlightField!=null){StringBuffer highlightName = new StringBuffer();Arrays.stream(highlightField.fragments()).forEach(f->{highlightName.append(f.toString());});sourceAsMap.put("name",highlightName);}});return goodsList;}

效果:

爬梯:ElasticSearch分布式搜索引擎相关推荐

  1. ElasticSearch分布式搜索引擎从入门到实战应用(入门篇-基本命令操作)

    ElasticSearch分布式搜索引擎从入门到实战应用(入门篇) 1.入门须知 2.ElasticSearch概述 2.1.ES简介 2.2.应用场景 3.ES和Solr的对比 3.1.ES作用 3 ...

  2. Elasticsearch——分布式搜索引擎01(索引库、文档、RestAPI、RestClient、拼音分词器、IK分词器)

    Elasticsearch--分布式搜索引擎01(索引库.文档.RestAPI.RestClient.拼音分词器.IK分词器) 一.初识 elesticsearch 1.1 简介 1.2 倒排索引(重 ...

  3. ElasticSearch分布式搜索引擎——从入门到精通

    ES分布式搜索引擎 注意: 在没有创建库的时候搜索,ES会创建一个库并自动创建该字段并且设置为String类型也就是text 什么是elasticsearch? 一个开源的分布式搜索引擎,可以用来实现 ...

  4. elasticsearch分布式搜索引擎详细使用总结

    文章目录 一.初识elasticsearch 1.1.ES了解 1.1.1.elasticsearch的作用 1.1.2.ELK技术栈 1.1.3.elasticsearch和lucene 1.1.4 ...

  5. 大数据(二)Elasticsearch 分布式搜索引擎(存索引、索引搜索)

    一.Elasticsearch 存索引, Hbase 里存原数据 例如:一条告警上报过来,会同时存Hbase, ES里,Hbase存原数据,ES里只存索引(包含告警ID, 告警级别,告警状态,告警时间 ...

  6. ElasticSearch分布式搜索引擎-03

    1.数据聚合 聚合可以让我们极其方便的实现对数据的统计.分析.运算.查询速度非常快,可以实现近实时搜索效果 1.1.聚合的种类 聚合常见的有三类: 桶(Bucket)聚合:用来对文档做分组 TermA ...

  7. Elasticsearch 分布式搜索引擎 -- 自动补全(拼音分词器、自定义分词器、自动补全查询、实现搜索框自动补全)

    文章目录 1. 自动补全 1.1 拼音分词器 1.2.1 自定义分词器 1.2.2 小结 1.2 自动补全 1.3 实现酒店搜索框自动补全 1.3.1 修改酒店映射结构 1.3.2 修改HotelDo ...

  8. 项目1在线交流平台-6.Elasticsearch分布式搜索引擎-3.ES结合Kafka应用-开发社区搜索功能

    文章目录 功能需求 一.Service层处理操作ES服务器的数据 二.Controller层处理帖子添加和评论事件请求 1.添加帖子时-触发事件-发布消息 2. 添加评论时-触发发帖事件-发布消息 三 ...

  9. Elasticsearch 分布式搜索引擎 -- elasticsearch-analysis-pinyin 拼音分词器的安装和介绍

    1. 拼音分词器 要实现根据字母做补全,就必须对文档按照拼音分词.在GitHub上恰好有elasticsearch的 拼音分词插件. 7.12.1 版本(因为我的es是7.12.1版本) 1.1.1 ...

最新文章

  1. SystemCenter2012SP1实践(31)P2V迁移故障一则
  2. 关于ASP.Net的导入导出的[转]
  3. Spring Boot怎么样处理静态资源(静态资源映射规则)_Web开发
  4. cocos2d-x初探学习笔记(9)--粒子系统
  5. python如何安装扩展库openpyxl和numpy_Python第三方库之openpyxl(2)
  6. 演练 开心餐厅 0929
  7. python 微服务 etcd_python etcd api
  8. java环境变量配置方法
  9. java js 打开摄像头_js调用网络摄像头
  10. 惠普局域网共享打印机设置_已解决: hp1106局域网共享打印机共享 - 惠普支持社区 - 817337...
  11. DEA模型及matlab应用1:CCR模型与BCC模型
  12. Fingerprint 解锁流程
  13. php实现wav转mp3,求,用PHP实现MP3转WAV后生成波形图的方法
  14. 基于python学生档案管理系统的设计与实现.rar(毕业论文+程序源码+答辩PPT)
  15. 编写类的步骤编写测试类
  16. Tomcat重启单个服务
  17. 人生效率手册:如何卓有成效地过好每一天--By张萌姐姐--读书笔记
  18. Gson的JsonParser使用
  19. JavaWeb视频教程
  20. 理查马文价值导向选股法则

热门文章

  1. debian linux修改网卡配置,Debian-Linux配置网卡网络方法说明
  2. 未来,中国的互联网会是什么样子?
  3. MATLAB程序转换为exe可执行文件
  4. java原创迷宫寻宝游戏(附项目)
  5. git里面怎么复制粘贴
  6. 八个最好的轻量级Linux发行版ZT
  7. 程序员找工作有哪些面试技巧
  8. 学习笔记之——matlab三次曲线拟合
  9. JavaSript严格模式use strict详解
  10. 【汇正财经】热点板块有什么特征?