文章目录
官方文档
基本概念
上面这篇文章可以对其有个很好的理解
1、Index
索引这个词在 ElasticSearch 会有三种意思:
1)、索引(名词)
类比传统的关系型数据库领域来说,索引相当于SQL中的一个数据库(Database)
。索引由其名称(必须为全小写字符)进行标识。(现在看来更相当于数据库的Table)
2)、索引(动词)
保存一个文档到索引(名词)的过程。这非常类似于SQL语句中的 INSERT关键词。如果该文档已存在时那就相当于数据库的UPDATE。
3)、倒排索引
关系型数据库通过增加一个B+树索引到指定的列上,以便提升数据检索速度。索引ElasticSearch 使用了一个叫做 倒排索引
的结构来达到相同的目的。
2、Type(弃用)
一个Index下支持多个Type–有点类似于消息队列一个topic下多个group的概念
Type
可以理解成关系数据库中Table。
之前的版本中,索引和文档中间还有个类型的概念,每个索引下可以建立多个类型,文档存储时需要指定index和type。
从6.0.0开始单个索引中只能有一个类型,7.0.0以后将将不建议使用,8.0.0 以后完全不支持。
弃用该概念的原因:
我们虽然可以通俗的去理解Index比作 SQL 的 Database,Type比作SQL的Table。但这并不准确,因为如果在SQL中,Table 之前相互独立,同名的字段在两个表中毫无关系。但是在ES中,同一个Index 下不同的 Type 如果有同名的字段
,他们会被 Luecence当作同一个字段
,并且他们的定义必须相同。
而Type字段并没有多少意义。目前Type已经被Deprecated,在7.0开始,一个索引只能建一个Type为_doc
去除type就是为了提高es的效率
3、Document
Document
等同于关系型数据库表中的行。(Document相当于数据库的一行记录)
_index
文档所属索引名称。
_type
文档所属类型名。
_id
Doc的主键。在写入的时候,可以指定该Doc的ID值,如果不指定,则系统自动生成一个唯一的UUID值。
_version
文档的版本信息。Elasticsearch通过使用version来保证对文档的变更能以正确的顺序执行,避免乱序造成的数据丢失。
_seq_no
严格递增的顺序号,每个文档一个,Shard级别严格递增,保证后写入的Doc的_seq_no
大于先写入的Doc的_seq_no。
primary_term
primary_term也和_seq_no
一样是一个整数,每当Primary Shard发生重新分配时,比如重启,Primary选举等,_primary_term会递增1
found
查询的ID正确那么ture, 如果 Id 不正确,就查不到数据,found字段就是false。
_source
文档的原始JSON数据。
4、其他
- Field:相当于数据库的Column (属性就是列名)
- Mapping:相当于数据库的Schema( schema是元数据的一个抽象集合,包含一套schema component: 主要是元素与属性的声明、复杂与简单数据类型的定义 )
- DSL:相当于数据库的SQL(给我们读取Elasticsearch数据的API)
Docker中安装
下载(全部)
docker pull elasticsearch:[版本] 存储和检索数据
docker pull kibana:[版本] 可视化检索数据
# 版本要一致
配置(elasticsearch)
# 将docker里的目录挂载到linux的/mydata目录中
# 修改/mydata就可以改掉docker里的
mkdir -p /mydata/elasticsearch/config
mkdir -p /mydata/elasticsearch/data
# es可以被远程任何机器访问
echo "http.host: 0.0.0.0" >/mydata/elasticsearch/config/elasticsearch.yml
# 递归更改权限,es需要访问(不建议)
chmod -R 777 /mydata/elasticsearch/
启动(elasticsearch)
# 9200是用户交互端口 9300是集群心跳端口
# -e指定是单阶段运行
# -e指定占用的内存大小,生产时可以设置32G
# -v来挂载,修改前者就是修改后者,装插件不用进容器内部了
docker run --name elasticsearch -p 9200:9200 -p 9300:9300 \
-e "discovery.type=single-node" \
-e ES_JAVA_OPTS="-Xms64m -Xmx512m" \
-v /mydata/elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml \
-v /mydata/elasticsearch/data:/usr/share/elasticsearch/data \
-v /mydata/elasticsearch/plugins:/usr/share/elasticsearch/plugins \
-d elasticsearch:7.4.2
# 设置开机启动elasticsearch
docker update elasticsearch --restart=always
权限
如何想要修改文件,结果没有权限;怎么办呢?
# r (读) = 4
# w (写) = 2
# x (可执行) = 1
# 无权限 = 0 特定用户类的权限数字是该类的权限值之和。
# setuid = 4
# setgid = 2
# sticky = 1
# no changes = 0 接下来的三位数的含义与使用三位数时相同。
chmod -R 777 #使用这个可以让你拥有所有全县(4+2+1 = 7)(但是并不建议使用该命令)
对文件或目录
设置777权限意味着它将对所有用户都是可读、可写和可执行的,并且可能会带来巨大的安全风险。
例如,如果你以递归方式将 /var/www 目录下所有文件和子目录的权限更改为777,则系统上的任何用户都可以创建、删除或修改该目录中的文件。
如果你的Web服务器遇到权限问题,请将文件的所有权更改为运行应用程序的用户,并将文件的权限设置为644,将目录的权限设置为755,而不是递归地将权限设置为777。
可以使用chown命令更改文件所有权,使用chmod命令更改权限。
假设您的服务器上有一个应用程序以用户“www”身份运行。
要设置要运行的正确权限,请执行以下操作:
chown -R www: /var/www
find /var/www -type d -exec chmod 755 {} \;
find /var/www -type f -exec chmod 644 {} \;
只有root用户、文件所有者或具有sudo权限的用户才能更改文件的权限。
使用chmod时要格外小心,特别是在递归更改权限的时候。
启动(kibana)
# kibana指定了了ES交互端口9200 # 5600位kibana主页端口
docker run --name kibana -e ELASTICSEARCH_HOSTS=http://192.168.56.10:9200 -p 5601:5601 -d kibana:7.4.2
# 设置开机启动kibana
docker update kibana --restart=always
测试
http://192.168.56.10:9200 #浏览器或者请求连接的工具打开,查看版本信息
初步使用
ES里面存的都是json文档
1、基本信息查看
都是主机地址加/_cat……
GET /_cat/nodes
:查看所有节点 (*代表主节点)GET /_cat/health
:查看es健康状况GET /_cat/master
:查看主节点GET/_cat/indicies
:查看所有索引 ,等价于mysql数据库的show databases;
2、新增
# PUT新增
# # 在customer索引下的external类型下保存1号数据
PUT customer/external/1
# POSTMAN输入
http://192.168.56.10:9200/customer/external/1
# 同时在请求体中加入json数据就行了
PUT和POST区别
- POST不指定id,一直发送请求,会一直(指定不存在的id)新增(自动生成唯一标识id)。指定id后,继续以这个id发送请求,就是(指定存在的id)更新操作了,会迭代(根据内容变化)版本号
- PUT可以新增也可以修改,但是必须指定id,版本号也会一直迭代
所有的请求成功后,会返回
返回数据:
带有下划线开头的,称为元数据,反映了当前的基本信息。
{
"_index": "customer", 表明该数据在哪个数据库下;
"_type": "external", 表明该数据在哪个类型下;
"_id": "1", 表明被保存数据的id;
"_version": 1, 被保存数据的版本
"result": "created", 这里是创建了一条数据,如果重新put一条数据,则该状态会变为updated,并且版本号也会发生变化。
"_shards": {
"total": 2,
"successful": 1,
"failed": 0
},
"_seq_no": 0,
"_primary_term": 1
}
3、查询
使用GET /customer/external/1
或者http://192.168.56.10:9200/customer/external/1
发送请求,然后返回:
{
"_index": "customer",
"_type": "external",
"_id": "1",
"_version": 1,
"_seq_no": 1,//并发控制字段,每次更新都会+1,用来做乐观锁
"_primary_term": 1,//同上,主分片重新分配,如重启,就会变化
"found": true,
"_source": {
"name": "John Doe"
}
}
更新
就是当两个人并发操作这一个name(_source中的)时,前一个人操作后(请求链接后加if_seq_no=1&if_primary_term=1
),这个_seq_no每次更新操作后都会改变,后一个人再按原来的操作(需要最新的这个值)就会报错error(类似乐观锁,需要有if_seq_no=1&if_primary_term=1
才会出现这种情况)
4、更新
# 使用_update,需要用"doc";不然会出现解析异常
POST customer/externel/1/_update
{
"doc":{
"name":"111"
}
}
或者
POST customer/externel/1
{
"name":"222"
}
或者
PUT customer/externel/1
{
"name":"222"
}
- POST带_update,更新的时候会对比数据是否改变,没有变化则不会改变版本号等
- POST不带_update以及PUT操作每次更新都会改变版本号
对于大并发更新,不带update
对于大并发查询偶尔更新,带update;对比更新,重新计算分配规则
5、删除
DELETE customer/external/1
DELETE customer
-
elasticsearch并没有提供删除类型的操作,只提供了删除索引和文档的操作 (type现在弃用了)
-
重复删除会找不到,删除后也查询不到
-
删除索引后,查询所有索引就查不到了
6、bulk批量API
POST 主机地址//customer/external/_bulk
#两行为一个整体
{"index":{"_id":"1"}}
{"name":"a"}
{"index":{"_id":"2"}}
{"name":"b"}
#注意格式json和text均不可,要去kibana里Dev Tools
#格式
{action:{metadata}}\n
{request body }\n
{action:{metadata}}\n
{request body }\n
- 某一条执行发生失败时,其他的数据仍然能够接着执行,也就是说彼此之间是独立的
- 当bulk api返回时,它将提供每个动作的状态(与发送的顺序相同),所以您可以检查是否一个指定的动作是否失败了
在kibana里Dev Tools的例子
POST /customer/external/_bulk
{"index":{"_id":"1"}}
{"name":"John Doe"}
{"index":{"_id":"2"}}
{"name":"John Doe"}
整个ES执行批量操作
POST /_bulk
{"delete":{"_index":"website","_type":"blog","_id":"123"}}
{"create":{"_index":"website","_type":"blog","_id":"123"}}
{"title":"my first blog post"}
{"index":{"_index":"website","_type":"blog"}}
{"title":"my second blog post"}
{"update":{"_index":"website","_type":"blog","_id":"123"}}
{"doc":{"title":"my updated blog post"}}
7、批量导入数据
准备一份文档样本,每一个都有下列的schema(模式)。可以理解为一种规范。
{
"account_number": 1,
"balance": 39225,
"firstname": "Amber",
"lastname": "Duke",
"age": 32,
"gender": "M",
"address": "880 Holmes Lane",
"employer": "Pyrami",
"email": "amberduke@pyrami.com",
"city": "Brogan",
"state": "IL"
}
测试
导入测试数据 (也可以在其他地方找到测试数据)
最后执行:
POST bank/account/_bulk # 必须指定索引 (就是数据库==类比)
上面的数据
进一步检索
1、查询
两种方式:
- 通过REST request uri 发送搜索参数 (uri +检索参数)
- 通过REST request body 来发送它们(uri+请求体)
#第一种
GET ……/_search?q=*&sort=account_number:asc
#第二种
GET ……/_search
{
"query": { "match_all": {} }, # 查询条件:全部
"sort": [ # 排序条件
{ "account_number": "asc" }, # 某个字段的某种顺序
{ "balance":"desc"}
]
}
2、复杂查询
Elasticsearch提供了一个可以执行查询的Json风格的DSL(domain-specific language领域特定语言) 。(可以类比sql)
格式
# 查询时,除了query、sort还有许多其他条件
GE1T ……/_search
{
QUERY_NAME:{ # 使用的功能
FIELD_NAME:{ # 功能参数
ARGUMENT:VALUE,
ARGUMENT:VALUE,...
}
}
}
# "from": 0 从第几条文档开始查
# "size": 0 查询几条数据
# "_source":["……"] 查询指定字段
条件查询,类似where、like等等
- match适用于全文检索;字符串等;文本字段
- term适用于精确检索;比如数字(年龄多少等等);非文本字段
#"query": {
# "match": {
# "……": "……" 某个字段匹配某个值
# }
# }
# 字符串检索是全文检索,会分词查询
"query": {
"match": {
"address": "kings"
}
}
# match_phrase就是不分词查询
# 短语匹配
"query": {
"match_phrase": {
"address": "mill road"
}
}
# 不分词且完全匹配
# 使用keyword,匹配的条件就是要显示字段的全部值,要进行精确匹配的
"query": {
"match_phrase": {
"address.keyword": "990 Mill"
}
}
# multi_match指定多个字段匹配query,带分词
"query": {
"multi_match": {
"query": "mill",
"fields": [ # state和address有mill子串 谁有都可以
"state",
"address"
]
}
}
# bool复合查询
"query":{
"bool":{ #
"must":[ # 必须有这些字段 (匹配了得分,相关性得分)
{"match":{"address":"mill"}},
{"match":{"gender":"M"}}
],
"must_not": [], #必须不匹配
"should": [] #可以匹配,但不匹配也没关系;匹配了会是个加分项(相关性得分)
"filter": { # query.bool.filter
"range": { # 区间
"balance": { # 哪个字段
"gte": "10000", # 大于
"lte": "20000" # 小于
}
}
}
}
}
# term查询非文本,主要是精确字段
"query": {
"term": {
"age": "111"
}
}
在bool
查询中,must
, should
和must_not
元素都被称为查询子句 。 文档是否符合每个“must”或“should”子句中的标准,决定了文档的“相关性得分”。 得分越高,文档越符合您的搜索条件。 默认情况下,Elasticsearch返回根据这些相关性得分排序的文档。 must_not
子句中的条件被视为过滤器。它影响文档是否包含在结果中,但不影响文档的评分方式。 相关性得分即是_score
。
aggregations 执行聚合
可以类比数据库中的group还有聚合函数
#格式
"aggs":{ # 聚合
"aggs_name":{ # 这次聚合的名字,方便展示在结果集中
# terms:看值的可能性分布,会合并锁查字段,给出计数即可
# avg:看值的分布平均
"AGG_TYPE":{} # 聚合的类型(avg,term,terms)
}
}
# 例如
"aggs":{ # 聚合
"ageAgg": { # 聚合的名字,随便起
"terms": { # 看值的可能性分布,大概会返回这个age的所有种类及当前种类的个数等
"field": "age",
"size": 10
}
},
"ageAvg": {
"avg": { # 看age值的平均
"field": "age"
}
}
}
#当然,聚合下可以嵌套聚合,即子聚合;即按照要求分组后的数据,再按要求求出聚合结果
"aggs": {
"ageAgg": {
"terms": { # 看分布
"field": "age",
"size": 100
},
"aggs": { # 与terms并列
"ageAvg": { #平均
"avg": {
"field": "balance"
}
}
}
}
}
# 自然还有很多复杂情况
Mapping字段映射
1、字段类型
核心数据类型
- 字符串
text
⽤于全⽂索引,搜索时会自动使用分词器进⾏分词再匹配keyword
不分词,搜索时需要匹配完整的值
- 数值
- 整型: byte,short,integer,long
- 浮点型: float, half_float, scaled_float,double
- 日期: date
- 范围
- integer_range, long_range, float_range,double_range,date_range
- gt,lt,e
- 布尔:boolean
- 二进制:binary 会把值当做经过 base64 编码的字符串,默认不存储,且不可搜索
复杂数据类型
- 对象:object 一个对象中可以嵌套对象
- 数组:Array
嵌套类型
- nested 用于json对象数组
2、查看mapping信息
(可以类比数据库中表的所有字段的类型)
GET ……/_mapping
3、创建映射
PUT /my_index # 创建索引 (类比数据库)
{
"mappings": {
"properties": { # 给字段加类型
"age": {
"type": "integer"
},
"email": {
"type": "keyword" # 指定为keyword
},
"name": {
"type": "text" # 全文检索。保存时候分词,检索时候进行分词匹配
}
}
}
}
4、给已有索引添加新的映射
不可以使用创建映射的方法添加
PUT /my_index/_mapping
{
"properties": {
"employee-id": {
"type": "keyword",
"index": false # 字段不能被检索,默认为true
}
}
}
5、更新映射(数据迁移)
对于已经存在的字段映射,我们不能更新。因为已有的字段数据,在更新之后可能会失效。 更新必须创建新的索引,进行数据迁移。
数据迁移
首先要创建新的索引,并且指定映射
# 没有类型时的迁移
POST _reindex
{
"source":{
"index":"twitter" #旧索引
},
"dest":{
"index":"new_twitters" #新索引
}
}
#有类型时的迁移
POST _reindex
{
"source":{
"index":"twitter",
"type":"twitter" #类型
},
"dest":{
"index":"new_twitters"
}
}
分词
1、标准分词器
一个tokenizer(分词器)接收一个字符流,将之分割为独立的tokens
(词元,通常是独立的单词),然后输出tokens流。
elasticsearch提供了很多内置的分词器(标准分词器),可以用来构建custom analyzers(自定义分词器)。
POST _analyze
{
"analyzer": "standard", # ES自带标准分词器
"text": "The 2 Brown-Foxes bone."
}
# 结果就是这句话按照空格分词
一般标准分词器都是支持英文的
2、中文分词器(ik分词器)
所有的语言分词,默认使用的都是“Standard Analyzer”,但是这些分词器针对于中文的分词,并不友好。为此需要安装中文的分词器。
- 安装插件后有些服务没法用了,可能时内存不够,需要分配。
第一种
如果在docker中安装elasticsearch时,把配置文件 /elasticsearch/plugins
映射到服务器主机中了,就可以在该主机的该目录下下载 elasticsearch-analysis-ik-7.x.x.zip
文件,然后解压,重启ES。
第二种
自然就是去容器内部安装了
curl http://主机ip:端口
可以查看正在使用该端口的程序的信息,如ES
-
进入docker的ES容器的plugin目录下
# docker exec -it 容器id /bin/bash (要是管理员才可以) docker exec -it elasticsearch /bin/bash pwd # 看看是不是已经进入容器内了 # 如果没有wget,安装就是了yum install wget等等 wget https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.x.x/elasticsearch-analysis-ik-7.x.x.zip # 解压 unzip elasticsearch-analysis-ik-7.x.x.zip -d ik # 要保证ik被移动到了plugins mv ik plugins/ # 权限也要适当赋予 # 重启服务 docker restart elasticsearch # 删除安装包(方法可以网上搜索) rm -rf elasticsearch-analysis-ik-7.x.x.zip
-
测试安装是否完成
# 默认分词器 GET _analyze { # "analyzer": "standard", "text":"我在学习ES" } # ik智能分词 GET _analyze { "analyzer": "ik_smart", "text":"我在学习ES" } # 最大的单词组合 GET _analyze { "analyzer": "ik_max_word", "text":"我在学习ES" } # 等等等,输出的分词效果都有所不同
3、自定义词库
两种方式:
- 实现一个服务,专门用来处理ik分词器的请求,让ik分词器给该项目发送请求。
- 使用nginx服务器,在nginx上维护扩展词库,然后ik分词器远程向nginx发送请求,获取新的单词。
nginx方式
# docker中安装并启动nginx
docker run -p 80:80 --name nginx -d nginx:1.10
# 查看是否启动
docker ps
#在相关目录下创建nginx文件夹用来映射nginx的配置文件,进入其中复制喽
mkdir nginx
docker container cp nginx:/etc/nginx .
#修改nginx文件夹下copy的nginx文件夹名字为conf,代表是nginx的配置文件夹
#会挂载这个文件夹和容器的配置文件映射
mv nginx conf
#停掉之前的nginx容器并删除
docker stop ${容器id} //停止容器
docker rm ${容器id} //删除容器
#之前的操作,因为是在docker中下载的,所以服务器中并没有nginx的配置,所以挂载没法对应;需要copy然后重新挂载
#重新创建一个nginx容器,加上要挂载的目录
docker run -p 80:80 --name nginx \
-v /目录/nginx/html:/usr/share/nginx/html \
-v /目录/nginx/logs:/var/log/nginx \
-v /目录/nginx/conf:/etc/nginx \
-d nginx:1.10
#启动成功后,服务器中的nginx文件夹下会多出两个文件夹,如上 -v后的
#在html文件夹下一个es文件夹,然后再该文件夹下再新建一个fenci.txt文件作为词库,这个就是ik分词器远程获取新单词的源头文件,编辑该文件;在其中加入新词语
mkdir es
cd es
vim fenci.txt
#为ik分词器配置远程词源的地址,也就是fenci.txt的地址
#进入/elasticsearch/plugins/ik/config目录中,会发现有个IKAnalyzer.cfg.xml文件
vim IKAnalyzer.cfg.xml
#然后配置远程扩展字典
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典 -->
<entry key="ext_dict"></entry>
<!--用户可以在这里配置自己的扩展停止词字典-->
<entry key="ext_stopwords"></entry>
<!--用户可以在这里配置远程扩展字典 -->
<entry key="remote_ext_dict">http://192.168.56.10/es/fenci.txt</entry>
<!--用户可以在这里配置远程扩展停止词字典-->
<!-- <entry key="remote_ext_stopwords">words_location</entry> -->
</properties>
#最后,重启ES容器,就可以了
SpringBoot集成ES
这些东西可以看官方文档,一般最新的好用
java操作es有两种:
- 9300:TCP 弃用啦
- 9200:HTTP
- jestClient 、 RestTemplate 、 HttpClient 都是,但不用
- Elasticsearch-Rest-Client : 官方RestClient ,使用
1、导入依赖
<!-- Elasticsearch-Rest-Client -->
<!-- 版本号与ELK版本匹配 -->
<!-- ELK即Elasticsearch、Logstash、Kibana -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.4.2</version>
</dependency>
<!-- 如果springboot自动依赖了ES,且版本不一致,需要我们修改 -->
<properties>
<java.version>1.8</java.version>
<elasticsearch.version>7.4.2</elasticsearch.version>
</properties>
2、创建配置类
@Configuration
public class ElasticSearchConfig {
public static final RequestOptions COMMON_OPTIONS;
static {
//es添加了安全访问规则,访问es需要添加一个安全头,就可以通过requestOptions设置
//官方建议把requestOptions创建成单实例
RequestOptions.Builder builder = RequestOptions.DEFAULT.toBuilder();
//这中间可能还有一些设置项,就是添加安全头之类的
COMMON_OPTIONS = builder.build();
}
@Bean
public RestHighLevelClient esRestClient() {
RestClientBuilder builder = null;
// 可以指定多个es
builder = RestClient.builder(new HttpHost(host, 9200, "http"));
RestHighLevelClient client = new RestHighLevelClient(builder);
return client;
}
}
3、保存数据
@Test
public void indexData() throws IOException {
// 设置索引
IndexRequest indexRequest = new IndexRequest ("users");
indexRequest.id("1");
User user = new User();//保存方式有多,建议使用实体类
//user.setUserName("张三");
//user.setAge(20);
//user.setGender("男");
String jsonString = JSON.toJSONString(user);//转为json数据
//传入要保存的内容,指定数据类型
indexRequest.source(jsonString, XContentType.JSON);
//执行创建索引和保存数据
//如果保存的id存在,不会报错,会使版本号增大
IndexResponse index = client.index(indexRequest, GulimallElasticSearchConfig.COMMON_OPTIONS);
System.out.println(index);
}
4、检索数据
@Test
public void find() throws IOException {
// 1 创建检索请求
SearchRequest searchRequest = new SearchRequest();
searchRequest.indices("bank");//查询哪个索引
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 构造检索条件
//sourceBuilder.query(); 等等直接用es检索时候的字段,都可以找到方法
sourceBuilder.query(QueryBuilders.matchQuery("address","mill"));//QueryBuilders工具类
//AggregationBuilders工具类构建AggregationBuilder
// 构建第一个聚合条件:按照年龄的值分布
TermsAggregationBuilder agg1 = AggregationBuilders.terms("agg1").field("age").size(10);// 聚合名称terms
sourceBuilder.aggregation(agg1);
// 构建第二个聚合条件:平均薪资
AvgAggregationBuilder agg2 = AggregationBuilders.avg("agg2").field("balance");
sourceBuilder.aggregation(agg2);
//System.out.println("检索条件"+sourceBuilder.toString());
searchRequest.source(sourceBuilder);//请求中放入检索条件
// 2 执行检索
SearchResponse response = client.search(searchRequest, GuliESConfig.COMMON_OPTIONS);//放入检索请求和规定,获得结果
// 3 分析响应结果
System.out.println(response.toString());
//获取响应结果的Buckets分析
Aggregations aggregations = response.getAggregations();
Terms agg21 = aggregations.get("agg2");
for (Terms.Bucket bucket : agg21.getBuckets()) {
String keyAsString = bucket.getKeyAsString();
System.out.println(keyAsString);
}
}
响应结果转化为实体类bean
SearchHits hits = response.getHits();//获取最外层hits
SearchHit[] hits1 = hits.getHits();//获取内层hits
//如果是自己想要的那一层就遍历
for (SearchHit hit : hits1) {
//hit.getId();
//hit.getIndex();
String sourceAsString = hit.getSourceAsString();//获得数据json格式,即字符串格式
Account account = JSON.parseObject(sourceAsString, Account.class);//转为实体类
System.out.println(account);
}