Elasticsearch学习笔记


Elasticsearch

1.什么是Elasticsearch:

2.为什么要使用Elasticsearch:

3.es和solr的区别:

4.倒排索引是什么:

5.安装es+kibana:

使用docker安装es:

1.获取es镜像

docker pull elasticsearch:7.2.0

2.启动es

docker run -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -e “ES_JAVA_OPTS=-Xms512m -Xmx512m” --name=es --net=elasticsearch

3.修改配置解决跨域问题

#进入到容器内部
docker exec -it es /bin/bash
#修改配置文件
vi /config/elasticsearch.yml
#追加内容
http.cors.enabled: true #允许跨域
http.cors.allow-origin: "*" #允许所有请求跨域
#退出容器
exit
#重启容器
docker restart es

4.如果通过ip:9200访问es服务配置:

http.host: 0.0.0.0

#es默认是以localhost:9200访问服务

5.测试安装成功:

访问http://ip:9200

安装Elasticsearch-head:

Elasticsearch-head是一款可视化Elasticsearch插件;安装这个直接使用谷歌插件即可。

安装ik分词器:

#进入容器内部
docker exec -it es /bin/bash
#进入到插件目录
cd /plugins
#安装插件
elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v7.2.0/elasticsearch-analysis-ik-7.2.0.zip
#退出容器
exit
#重启容器
docker restart es

安装kibana

kibana用来操作elasticsearch的一款可视化平台软件。

1.获取镜像

docker pull kibana:7.2.0 #注意:版本号一定要与elasticsearch版本号一致

2.启动kibana

docker run --name kibana --link=elasticsearch:test -p 5601:5601 -d kibana:7.2.0

3.Kibana在6.7以后的版本,支持了多种语言。并且自带在安装包里。修改方式如下:

#进入到kibana里面
docker exec -it kibana
#修改配置
vi /config/kibana.yml
#增加配置
i18n.locale: "zh-CN"
#重启容器

4.如果要使用ip:5601的方式访问

#修改kibana.yml
server.host: "192.168.2.102"

5.如果访问不到es:

elasticsearch.hosts: ["http://192.168.2.102:9200"]

6.访问页面:

http://ip:5601

6.es结构

1.索引indices(类似mysql的库)

es服务可以创建多个索引;

每一个索引默认被分为5片储存,每一个分片都会存在至少一个备份分片;

备份分片一般不会帮助检查数据,但是当es索引的查询压力特别大的时候,备份分片才会帮助检查数据;

备份分片必须放在不同的es服务中。

2.类型types(类似mysql中的表)

一个索引下,可以创建对个类型;

根据版本不同,创建的类型也不同。

es5.x版本,一个index下可以有多个type;

es6.x版本,一个index下可以创建一个type;

es7.x版本,一个index下没有type。

3.文档documents(类型mysql中的一条数据)

一个类型下可以有多个文档,这个文档类似于mysql中的多行数据。

4.字段fields(类似mysql中表的列)

一个文档中可以包含多个字段,类似mysql表中的列。

总结:

7.ik分词器操作方法:

1.ik分词器的分词方式:

ik_max_word:

ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合,适合 Term Query;

ik_smart :

ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”,适合 Phrase 查询。

2.使用方式:

ik_max_word:

POST _analyze
{
  "analyzer": "ik_max_word",
  "text": "我是大神仙"
}
################### 结果 #######################
{
  "tokens" : [
    {
      "token" : "我",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "CN_CHAR",
      "position" : 0
    },
    {
      "token" : "是",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "CN_CHAR",
      "position" : 1
    },
    {
      "token" : "大神",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "CN_WORD",
      "position" : 2
    },
    {
      "token" : "神仙",
      "start_offset" : 3,
      "end_offset" : 5,
      "type" : "CN_WORD",
      "position" : 3
    }
  ]
}

ik_smart:

POST _analyze
{
  "analyzer": "ik_smart",
  "text": "我是大神仙"
}
############# 结果 ###################
{
  "tokens" : [
    {
      "token" : "我",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "CN_CHAR",
      "position" : 0
    },
    {
      "token" : "是",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "CN_CHAR",
      "position" : 1
    },
    {
      "token" : "大",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "CN_CHAR",
      "position" : 2
    },
    {
      "token" : "神仙",
      "start_offset" : 3,
      "end_offset" : 5,
      "type" : "CN_WORD",
      "position" : 3
    }
  ]
}

3.自定义ik词典:

ik分词器,分词都是根据词典(ik的config目录中各种xxxx.dic就是词典)来分的,如果我们需要拓展分词,则可以自定义词典。

1.编写自定义词典:

#编写一个xlw.dic的词典
内容为:肖龙威

2.启用自定义词典:

修改ik的config目录的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">xlw.dic</entry>
	 <!--用户可以在这里配置自己的扩展停止词字典-->
	<entry key="ext_stopwords">custom/ext_stopword.dic</entry>
 	<!--用户可以在这里配置远程扩展字典 -->
	<entry key="remote_ext_dict">location</entry>
 	<!--用户可以在这里配置远程扩展停止词字典-->
	<entry key="remote_ext_stopwords">http://xxx.com/xxx.dic</entry>
</properties>

3.测试是否成功:

POST _analyze
{
  "analyzer": "ik_max_word",
  "text": "我是肖龙威"
}

################### 结果 #####################
{
  "tokens" : [
    {
      "token" : "我",
      "start_offset" : 0,
      "end_offset" : 1,
      "type" : "CN_CHAR",
      "position" : 0
    },
    {
      "token" : "是",
      "start_offset" : 1,
      "end_offset" : 2,
      "type" : "CN_CHAR",
      "position" : 1
    },
    {
      "token" : "肖龙威",
      "start_offset" : 2,
      "end_offset" : 5,
      "type" : "CN_WORD",
      "position" : 2
    }
  ]
}

8.操作es的RESTFUL语法

GET请求用来获取数据

#查看索引信息
#以postman的方式访问
http://ip:9200/index
#以kibana的方式访问
GET /index

#查看文档信息
GET /index/type/doc_id #注意es7版本后没有类型

POST请求用来更新数据

POST /index/type/_search #查询文档,可以通过json来指定查询条件

POST /index/type/doc_id/_update #修改文档,修改内容写在json里

PUT请求用来创建索引

PUT /index #创建索引,可以通过json配置索引,还可以指定字段

DELETE请求用来删除索引和数据

DELETE /index #删除索引,会删除所有文档

DELETE /index/type/doc_id #删除指定的文档

9.Filed类型

官网地址https://www.elastic.co/guide/en/elasticsearch/reference/7.2/mapping-types.html

字符串类型

text:被用于全文检索,将当前的filed进行分词。

keyword:关键字,当前filed不会被分词。

数值类型

byte

short

integer

long

float

half_float:精度比float小一半

double

时间类型

date

布尔类型

boolean

二进制类型

binary:支持base64编码的string

范围类型

integer_range:赋值时无需指定具体的内容,只需储存一个范围即可,如gt、lt、gte、lte

long_range

double_range

float_range

date_range

经纬度类型

geo_point:用来储存经纬度

ip类型

ip

10.操作es

1.创建索引(不带字段)

#创建一个名为book的索引
PUT /book
{
  #对索引进行设置
  "settings": {
    #索引分片数为5"number_of_shards": 5,
    #索引每个分片的备份数为1"number_of_replicas": 1
  }
}

################ 结果 ######################
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "book"
}

2.创建一个带字段的索引

PUT /persion
{
  #设置索引
  "settings": {
    #索引切片数2"number_of_shards": 2,
    #索引切片的备份数
    "number_of_replicas": 1
  },
  #指定索引数据的结构
  "mappings": {
    #指定文档的filed  
    "properties": {
      #filed名称
      "name": {
        #filed的类型
        "type": "keyword",
        #filed是否能当做索引的条件
        "index": true,
        #是否需要额外储存
        "store": false
      },
      "age": {
        "type": "integer"
      },
      "birth": {
        "type": "date",
         #指定日期类型的格式化方式
        "format": ["yyyy/MM/dd HH/mm/ss"]
      },
      "describe": {
        "type": "text",
        "index": true,
        "store": false,
        #指定分词器为ik分词器
        "analyzer": "ik_max_word"
      }
    }
  }
}

################## 结果 #######################
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "persion"
}

为索引添加新字段: post index_name/_mapping方式即可

改变索引字段类型: 重建索引

3.添加一个文档

在es中唯一的标识_index(表示那个索引)、_type(表示那个类型,es5版本可以有多个类型;es6版本只能有一个类型,首选类型名称是 _doc;es7版本中没有类型,在7.0中,它_doc是路径的永久部分,代表端点名称而不是文档类型)、_id(表示文档ID),通过这三个字段来锁定一组文档。

指定文档id

#put /index/type/doc_id   指定文档id的方式提交
PUT /persion/_doc/1
{
  "name": "小白白",
  "age": "15",
  "birth": "1995/04/17 12/30/00",
  "describe": "我是小白白啊,大家好"
}

############# 结果 #########################

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

_index:那个索引;

_type:那个类型;

_id:文档id;

#也可以通过 post /index/type/doc_id  的方式创建指定文档id
POST /persion/_doc/3
{
  "name": "柯莉堃",
  "age": "16",
  "birth": "1995/04/17 12/30/00",
  "describe": "大叔大婶,大家好"
}

############# 结果 ################
{
  "_index" : "persion",
  "_type" : "_doc",
  "_id" : "3",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 4,
  "_primary_term" : 2
}

不指定文档id

POST /persion/_doc
{
  "name": "小嘿嘿",
  "age": "15",
  "birth": "1995/04/17 12/30/00",
  "describe": "我是小嘿嘿啊,大家好"
}

################ 结果 #########################

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

不指定id用post方式提交,es服务会随机分配一个id号。

批量添加

POST _bulk
{"create" : {"_index" : "class", "_id" : 4}}    
{"name" : "一班", "stu_count" : 10, "code" : "0004"}
{"index" : {"_index" : "class", "_id" : 5}}
{"create" : "二班", "stu_count" : 10, "code" : "0005"}

//create:如果文档不存在就创建,但如果文档存在就返回错误
//index 如果文档不存在就创建,如果文档存在就更新

//某一个操作失败,是不会影响其他文档的操作的,它会在返回结果中告诉你失败的详细的原因。

4.修改文档

覆盖修改

#覆盖修改需要指定每一个字段的值,不然就会被覆盖成null
PUT /persion/_doc/1
{
  "name": "大白",
  "age":"25",
  "birth": "2000/01/30 00/30/00",
  "describe": "呵呵呵呵"
}

不覆盖修改

#改指定字段,其它字段的值不会置为null
POST /persion/_doc/1/_update
{
  "doc":{
    "name": "大子白"
  }
}

######### 结果 ################################

{
  "_index" : "persion",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 4,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 8,
  "_primary_term" : 2
}

批量修改:

POST _bulk
{"update" : {"_index" : "hello","_id" : "1"}}
{"doc" : {"age" : 8}}
{"update" : {"_index" : "hello","_id" : "2"}}
{"doc" : {"age" : 4}}

5.删除操作

#DELETE /index/type/doc_id 删除文档
DELETE /persion/_doc/e__skHcBQnrHOuXw1gwm

#删除索引
DELETE /index

批量删除

POST _bulk
{"delete" : {"_index" : "class", "_id" : 4}}
{"delete" : {"_index" : "class", "_id" : 5}}

6.查询操作

1.term查询

term查询:代表完全匹配,不会对查询的关键字进行分词,而是直接把查询的关键字拿到分词字典中去匹配,并返回匹配到的对应的文档。

GET /persion/_doc/_search
{
  "from": 0,   #类似mysql中的limit ?,从那条文档开始返回
  "size": 3,   #类似mysql中的limit ?,* ,返回多少条文档
  "query":{
    "term":{
      #查询的filed : value
      "name": "小子"
    }
  }
}

############### 结果 ##########################

#! Deprecation: [types removal] Specifying types in search requests is deprecated.
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 0.5753642,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 0.5753642,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "臭小子在干吗啊"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "7",
        "_score" : 0.5753642,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "大萨达撒是"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "6",
        "_score" : 0.5753642,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "爱生气翁群翁无群"
        }
      }
    ]
  }
}

2.terms查询

terms查询:terms跟term查询机制是一样的,都不会将查询关键字进行分词,而是直接去分词字典中匹配,并将匹配的相关文档返回。

term跟terms的区别:

1.term只能根据一个字段的一个值查询一条文档,类似sql的 where id=1;
2.terms可以根据一个字段的多个值查询多条文档,类似sql的 where id=1 or id=2 ...。
GET /persion/_search 
{
  "from":0,
  "size": 3,
  "query": {
    "terms": {
      "name": [
        "大子白",
        "科学家",
        "小花花"
      ]
    }
  }
}

###################### 结果 #########################
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "大子白",
          "age" : "25",
          "birth" : "2000/01/30 00/30/00",
          "describe" : "呵呵呵呵"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "name" : "科学家"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : "小花花",
          "age" : "16",
          "birth" : "1995/04/17 12/30/00",
          "describe" : "我是小花花啊,大家好"
        }
      }
    ]
  }
}

3.match_all查询

match_all查询:匹配所有的文档。

GET /persion/_search
{
  "query": {
    "match_all": {}
  }
}

################# 结果 ####################
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 6,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "大子白",
          "age" : "25",
          "birth" : "2000/01/30 00/30/00",
          "describe" : "呵呵呵呵"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "name" : "科学家"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : "小花花",
          "age" : "16",
          "birth" : "1995/04/17 12/30/00",
          "describe" : "我是小花花啊,大家好"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.0,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "臭小子在干吗啊"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "7",
        "_score" : 1.0,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "大萨达撒是"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "6",
        "_score" : 1.0,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "爱生气翁群翁无群"
        }
      }
    ]
  }
}

4.match查询

match查询:match查询属于高层查询,它会将你查询的字段类型不同,而采取不同的查询方式。

1.查询的如果是日期字段或者数值字段,它会将你的查询字符串转化为对应的日期或者数值;
2.如果查询的是一个不能分词的keyword字段,match查询不会对你的查询关键字进行分词;
3.如果查询的是一个可以被分词的text字段,match会将你查询的关键字进行分词,去分词库中匹配指定的值,并将对应   值的文档返回。
4.match查询的底层实际是多个term查询,将多个term查询的结果封装到一起。
根据一个字段包含单个关键字查询
GET /persion/_search
{
  "query": {
    "match": {
      "name": "大子白"
    }
  }
}

############ 结果 ################

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.6739764,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.6739764,
        "_source" : {
          "name" : "大子白",
          "age" : "25",
          "birth" : "2000/01/30 00/30/00",
          "describe" : "呵呵呵呵"
        }
      }
    ]
  }
}
根据一个字段包含多个关键字查询

根据一个字段的值包含多个查询关键字,采用and或者or的方式连接。

GET /persion/_search
{
  "query": {
    "match": {
      #filed
      "describe": {
        #查询的内容
        "query": "呵呵 大",
        "operator": "or"      #包含呵呵or大
      }
    }
  }
}

############ 结果 #############
{
  "took" : 5,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 2.6921797,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 2.6921797,
        "_source" : {
          "name" : "大子白",
          "age" : "25",
          "birth" : "2000/01/30 00/30/00",
          "describe" : "呵呵呵呵"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "7",
        "_score" : 1.6183326,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "大萨达撒是"
        }
      }
    ]
  }
}
GET /persion/_search
{
  "query": {
    "match": {
      "describe": {
        "query": "爱 生气",  
        "operator": "and"   #字段值包含爱and生气
      }
    }
  }
}
################## 结果 ###########################
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 3.179408,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "7",
        "_score" : 3.179408,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "我爱这个生气"
        }
      }
    ]
  }
}

5.mulit_match查询

match是针对一个filed做索引,mulit_match是针对多个filed进行索引,多个filed对应着一个查询关键字。

GET /persion/_search
{
  "query": {
    "multi_match": {
      "query": "呵呵",
      "fields": ["name","describe"]  #字段name或者describe包含 呵呵 都查询出来
    }
  }
}
############### 结果 ###################
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 3.1003478,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 3.1003478,
        "_source" : {
          "name" : "大子白",
          "age" : "25",
          "birth" : "2000/01/30 00/30/00",
          "describe" : "呵呵呵呵"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "9",
        "_score" : 1.89712,
        "_source" : {
          "name" : "呵呵",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "我是小子白"
        }
      }
    ]
  }
}

6.id查询

id查询就是根据文档的id进行查询,类似sql的 where id=?

GET /persion/_doc/1 #查询索引persion中id为1的文档,这里的_doc不是类型名,而是es7版本的固定写法

############# 结果 ###############
{
  "_index" : "persion",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 4,
  "_seq_no" : 8,
  "_primary_term" : 2,
  "found" : true,
  "_source" : {
    "name" : "大子白",
    "age" : "25",
    "birth" : "2000/01/30 00/30/00",
    "describe" : "呵呵呵呵"
  }
}

7.ids查询

ids查询:根据多个id查询,类型sql的where id in (1,2,3)。

GET /persion/_search
{
  "query": {
    "ids": {
      #指定多个文档id
      "values": [1,2,3]
    }
  }
}
############ 结果 #############
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "大子白",
          "age" : "25",
          "birth" : "2000/01/30 00/30/00",
          "describe" : "呵呵呵呵"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "name" : "科学家"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : "小花花",
          "age" : "16",
          "birth" : "1995/04/17 12/30/00",
          "describe" : "我是小花花啊,大家好"
        }
      }
    ]
  }
}

8.prefix查询

prefix查询,通过一个关键字去匹配一个字段内容的前缀,从而查询到指定的文档。

GET /persion/_search
{
  "query": {
    "prefix": {
      "name": {
        "value": "小"  #查询name字段内容以小开头的文档
      }
    }
  }
}
############### 结果 ##############
{
  "took" : 14,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : "小花花",
          "age" : "16",
          "birth" : "1995/04/17 12/30/00",
          "describe" : "我是小花花啊,大家好"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.0,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "臭小子在干吗啊"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "6",
        "_score" : 1.0,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "爱生气翁群翁无群"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "7",
        "_score" : 1.0,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "我爱这个生气"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "8",
        "_score" : 1.0,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "爱好把生气"
        }
      }
    ]
  }
}

9.fuzzy查询

fuzzy查询,模糊查询就是我们输入一个大概关键字,es就会通过大概关键字,匹配大概的结果,从而达到搜索有错别字的情形。

GET /persion/_search
{
  "query": {
    #模糊查询
    "fuzzy": {
      #字段
      "name": {
        "value": "大子百",   #查询关键字
        "prefix_length": 2, #前两个字符不能被模糊查询
        "fuzziness": "auto" #模糊性,它可以被设置为“0”, “1”, “2”或“auto”,推荐"auto"
      }
    }
  }
}

################ 结果 ################
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.2647465,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.2647465,
        "_source" : {
          "name" : "大子白",
          "age" : "25",
          "birth" : "2000/01/30 00/30/00",
          "describe" : "呵呵呵呵"
        }
      }
    ]
  }
}

10.wildcard查询

wildcard查询:通配符查询,跟mysql中的like查询相似,在查询关键字中指定通配符*或者占位符?。

GET /persion/_search
{
  "query": {
    "wildcard": {
      "name": {
        "value": "小*"   #查询name内容以"小"开头的所有文档
      }
    }
  }
}
################ 结果 ##################
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 5,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : "小花花",
          "age" : "16",
          "birth" : "1995/04/17 12/30/00",
          "describe" : "我是小花花啊,大家好"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.0,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "臭小子在干吗啊"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "6",
        "_score" : 1.0,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "爱生气翁群翁无群"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "7",
        "_score" : 1.0,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "我爱这个生气"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "8",
        "_score" : 1.0,
        "_source" : {
          "name" : "小子",
          "age" : 5,
          "birth" : "2000/02/02 12/30/30",
          "describe" : "爱好把生气"
        }
      }
    ]
  }
}

11.range查询

range查询:范围查询,只针对数值类型,对某一个数值字段进行大于或者小于的范围指定。

GET /persion/_search
{
  "query": {
    "range": {
      "age": {
        "gte": 15,   #大于等于15
        "lte": 25    #小于等于25
               		 #gt:大于		gte:大于等于	eq:等于	lte:小于等于	lt:小于   
      }
    }
  }
}

############### 结果 ###############
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "大子白",
          "age" : "25",
          "birth" : "2000/01/30 00/30/00",
          "describe" : "呵呵呵呵"
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : "小花花",
          "age" : "16",
          "birth" : "1995/04/17 12/30/00",
          "describe" : "我是小花花啊,大家好"
        }
      }
    ]
  }
}

12.regexp查询

regexp查询:正则查询,通过正则表达式去查询内容。

prefix、fuzzy、wildcard和regexp查询速率相对较低,如果要求速率比较高,应该避免去使用。

GET /book/_search
{
  "query": {
    "regexp": {
      "NO": "12[0-9]{4}"  #正则表达式只能作用在字符串类型的字段上
    }
  }
}

############## 结果 ###########################
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "book",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "射雕英雄传",
          "NO" : "123456"
        }
      },
      {
        "_index" : "book",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : "天龙八部",
          "NO" : "123451"
        }
      }
    ]
  }
}

13.scroll查询

from&size和scroll&size的区别:

1.from&size是有限制的,from和size二者之和的数据不能超过1w条;
2.from&size的原理:
  1).将用户查询的关键词进行分词;
  2).将词汇拿到分词库中进行检索,得到多个文档的id;
  3).根据文档id去各个分片获取指定的文档,这一步比较耗时;
  4).将获取到的数据根据_score进行排序,耗时较长;
  5).根据from的值将获取到的文档舍去一部分;
  6).根据size的值返回对应条数数据。
3.scroll&size的原理:
  1).将用户查询的关键词进行分词;
  2).将词汇拿到分词库中进行检索,得到多个文档的id;
  3).将文档id存放在一个es上下文中;
  4).根据size(相当于一个指针)的数值去es上下文中检索指定个数文档,如果es上下文中的id被拿完,则es上下文会被删除;
  5).如果需要下一页数据,直接去es上下文中继续根据size检索文档。
4.scroll查询,不适合做实时查询。
5.from&size会造成数据的浪费;
7.scroll的性能比from好。
8.scroll相当于一次性把所有满足查询条件的数据全部缓存,需要的时候根据缓存id去取.
第一次查询
#第一次查询,会得到首页并且把文档ID信息存放到es上下文中,和scroll_id
#scroll=5m es上下文的保存时间为5分钟,如果时间到了则es上下文会自动被删除
GET /persion/_search?scroll=5m
{
  "size": 3,     #返回3条数据
  "query": {
    "match_all": {}   #查询方式匹配所有
  },
  "sort": [         #指定排序
    {
      "age": {        
        "order": "asc"    #按照年龄升序排序
      }
    }
  ]
}

################## 结果 ##################
{
  "_scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDnF1ZXJ5VGhlbkZldGNoAhZnemVBbVluNVJxdU9NbVAybngxei13AAAAAAAAGugWYlVDYUtJbG9SRHFBWFBaV3Q1MFhsZxZnemVBbVluNVJxdU9NbVAybngxei13AAAAAAAAGukWYlVDYUtJbG9SRHFBWFBaV3Q1MFhsZw==",
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 7,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "6",
        "_score" : null,
        "_source" : {
          "name" : "上官婉儿",
          "age" : 18,
          "birth" : "2002/02/02",
          "describe" : "我不是一个法师",
          "phone" : 15174692184
        },
        "sort" : [
          18
        ]
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : null,
        "_source" : {
          "name" : "柯莉堃",
          "age" : 24,
          "birth" : "1997/04/17",
          "describe" : "我是柯莉堃啊",
          "phone" : 18946297416
        },
        "sort" : [
          24
        ]
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : null,
        "_source" : {
          "name" : "肖战",
          "age" : 25,
          "birth" : "1996/03/15",
          "describe" : "招黑体质",
          "phone" : 13594462687
        },
        "sort" : [
          25
        ]
      }
    ]
  }
}
继续查询(下一页)
#下一页,查询下一页是直接根据es上下文中继续找,所以不需要指定索引
GET /_search/scroll
{
  #指定scroll_id,根据这个es上下文,继续查找
  "scroll_id":"FGluY2x1ZGVfY29udGV4dF91dWlkDnF1ZXJ5VGhlbkZldGNoAhZnemVBbVluNVJxdU9NbVAybngxei13AAAAAAAAGugWYlVDYUtJbG9SRHFBWFBaV3Q1MFhsZxZnemVBbVluNVJxdU9NbVAybngxei13AAAAAAAAGukWYlVDYUtJbG9SRHFBWFBaV3Q1MFhsZw==",
   #指定es上下文的保存时间为1分钟
   "scroll":"1m"
}

################## 结果 ###################
{
  "_scroll_id" : "FGluY2x1ZGVfY29udGV4dF91dWlkDnF1ZXJ5VGhlbkZldGNoAhZnemVBbVluNVJxdU9NbVAybngxei13AAAAAAAAG1IWYlVDYUtJbG9SRHFBWFBaV3Q1MFhsZxZnemVBbVluNVJxdU9NbVAybngxei13AAAAAAAAG1MWYlVDYUtJbG9SRHFBWFBaV3Q1MFhsZw==",
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 7,
      "relation" : "eq"
    },
    "max_score" : null,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : null,
        "_source" : {
          "name" : "关菲菲",
          "age" : 50,
          "birth" : "1981/05/18",
          "describe" : "王者荣耀策划师",
          "phone" : 13517946268
        },
        "sort" : [
          50
        ]
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : null,
        "_source" : {
          "name" : "王宝强",
          "age" : 55,
          "birth" : "1979/05/18",
          "describe" : "无敌绿巨人",
          "phone" : 18849532476
        },
        "sort" : [
          55
        ]
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : null,
        "_source" : {
          "name" : "刘德华",
          "age" : 60,
          "birth" : "1973/01/12",
          "describe" : "天王华仔",
          "phone" : 15179461347
        },
        "sort" : [
          60
        ]
      }
    ]
  }
}
手动删除es上下文
#DELETE /_search/scroll/scroll_id   删除指定的es上下文
DELETE /_search/scroll/FGluY2x1ZGVfY29udGV4dF91dWlkDnF1ZXJ5VGhlbkZldGNoAhZnemVBbVluNVJxdU9NbVAybngxei13AAAAAAAAGQEWYlVDYUtJbG9SRHFBWFBaV3Q1MFhsZxZnemVBbVluNVJxdU9NbVAybngxei13AAAAAAAAGQIWYlVDYUtJbG9SRHFBWFBaV3Q1MFhsZw==

#删除所有的es上下文
DELETE _search/scroll/_all

14._delete_by_query查询删除

_delete_by_query查询删除:根据term、match等查询的方式删除大量的文档。

ps:如果你要删除的内容是index下的大部分数据,推荐创建一个全新的索引,将保留的文档内容放到新索引中。

POST /book/_delete_by_query
{
  "query":{
    "range":{
      "NO":{
        "gt":0  #把编号大于0的都删除
      }
    }
  }
}

15._update_by_query查询修改

_update_by_query: 根据索引的查询操作,并配合script脚本,一次性修改大量文档.

POST hello/_update_by_query
{
  "query" : {
    "term" : {
      "name" : "哆啦A梦"
    }
  },
  "script": {
    "lang": "painless",
    "source": "ctx._source.count = params.count",
    "params": {"count" : 500}
  }
}

16.bool查询

bool查询:复合过滤器,将多个查询条件,以一定的逻辑组合到一起。

must:所有的条件都必须满足,并且参与计算分值,类似sql的and;

should:所有的条件都可以满足,类似sql的or;

must_not:所有的条件都不能满足,类似sql的not;

filter:返回的文档必须满足filter子句的条件。但是不会像Must一样,参与计算分值。

GET /persion/_search
{
  "query": {
    "bool": {
      "should": [
        {
          "term": {
            "name": {
              "value": "柯莉堃"
            }
          }
        },
        
        {
          "term": {
            "name": {
              "value": "刘德华"
            }
          }
        },
        
        {
          "term": {
            "name": {
              "value": "肖战"
            }
          }
        }
      ],  #会把"柯莉堃"或者"刘德华"或者"肖战"的文档取出来
      
      "must": [
        {
          "range": {
            "age": {
              "gt": 20,
              "lt": 60
            }
          }
        }
      ],   #会把20<age<60的文档取出来
      
      "must_not": [
        {
          "match": {
            "describe": "体质"
          }
        }
      ],   #会把describe字段中包含"体质"的文档去除

	  "filter": [
        {
          "term": {
            "name": "柯莉堃"
          }
        }
      ]  #过滤掉name不是"柯莉堃"的所有文档
    }
  }
}

17.boosting查询

bootsting查询:可以帮助我们去影响查询后的score。

positive:只有匹配上positive的查询内容,才会被放到返回的结果集中;

negative:如果匹配上positive并且也匹配上negative,就可以降低文档的score;

negative_boost:指定系数,必须小于1.0;score = negative_boost*score。

关于查询时,分数如何计算:

1.查询的关键字在文档中出现的频次越高,分数也就越高;

2.指定的文档内容越短,分数越高;

3.我搜索的关键字会被分词,这个被分词的内容,被分词库匹配的个数越多,分数越高。

GET /persion/_search
{
  "query": {
    "boosting": {
      "positive": {
        "match": {
          "describe": "不是"  #describe中包含"不是"的文档返回
        }
      },  
      "negative": {
        "term": {
          "name": {
            "value": "关羽"   #如果查询的文档字段name的内容是"关羽"的降低score
          }
        }
      },
      "negative_boost": 0.5  #降低score的指数是0.5
    }
  }
}

################## 结果 ##################
{
  "took" : 12,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 2,
      "relation" : "eq"
    },
    "max_score" : 0.88964105,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "6",
        "_score" : 0.88964105,
        "_source" : {
          "name" : "上官婉儿",
          "age" : 18,
          "birth" : "2002/02/02",
          "describe" : "我不是一个法师",
          "phone" : 15174692184
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "7",
        "_score" : 0.4843276,
        "_source" : {
          "name" : "关羽",
          "age" : 65,
          "birth" : "1961/04/04",
          "describe" : "我不是历史的关羽",
          "phone" : 13579642589
        }
      }
    ]
  }
}

18.高亮查询

高亮查询,就是将你查询的关键字,以高亮的形式展示给客户端。

es提供了一个highlight属性,跟query同级,highlight属性还包含一些子属性:

fragment_size:指定高亮数据展示多少个字符回来;

pre_tags:指定前缀标签,如

post_tags:指定后缀标签,如;

fields:指定哪些字段以高亮的形式返回。

GET /persion/_search
{
  "query": {
    "match": {
      "describe": "无敌"
    }
  },
  
 "highlight": {
   "fields": {
     "describe": {}
   },
   "fragment_size": 10,
   "pre_tags": "<front color='red'>",
   "post_tags": "</front>"
 }
}

########### 结果 ###########
{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.7622693,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.7622693,
        "_source" : {
          "name" : "王宝强",
          "age" : 55,
          "birth" : "1979/05/18",
          "describe" : "无敌绿巨人",
          "phone" : 18849532476
        },
        "highlight" : {
          "describe" : [
            "<front color='red'>无敌</front>绿巨人"
          ]
        }
      }
    ]
  }
}

19.聚合查询

es聚合查询和sql的聚合查询类似,但是es聚合查询比sql聚合查询功能钢架强大。

语法:

GET /index/_search
{
	#指定聚合查询
	"aggs":{
        #自定义聚合查询的名称
		"name":{
            #指定聚合查询的查询类型
			"agg_type":{
                #指定需要查询的字段
				"field":value
			}
		}
	}
}
去重计数查询:

去重计数,cardinality,第一步先将返回文档中的一个指定的field进行去重,然后统计一共有多少条文档。

GET /persion/_search
{
  "aggs": {
    #为这个聚合查询起名为agg
    "agg": {
      #指定聚合类型为去重统计
      "cardinality": {
        #去重字段为"name"
        "field": "name"
      }
    }
  }
}
############# 结果 #############
{
  "took" : 996,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 8,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "柯莉堃",
          "age" : 24,
          "birth" : "1997/04/17",
          "describe" : "我是柯莉堃啊",
          "phone" : 18946297416
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : "刘德华",
          "age" : 60,
          "birth" : "1973/01/12",
          "describe" : "天王华仔",
          "phone" : 15179461347
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "name" : "肖战",
          "age" : 25,
          "birth" : "1996/03/15",
          "describe" : "招黑体质",
          "phone" : 13594462687
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.0,
        "_source" : {
          "name" : "王宝强",
          "age" : 55,
          "birth" : "1979/05/18",
          "describe" : "无敌绿巨人",
          "phone" : 18849532476
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "6",
        "_score" : 1.0,
        "_source" : {
          "name" : "上官婉儿",
          "age" : 18,
          "birth" : "2002/02/02",
          "describe" : "我不是一个法师",
          "phone" : 15174692184
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "7",
        "_score" : 1.0,
        "_source" : {
          "name" : "关羽",
          "age" : 65,
          "birth" : "1961/04/04",
          "describe" : "我不是历史的关羽",
          "phone" : 13579642589
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.0,
        "_source" : {
          "name" : "关菲菲",
          "age" : 50,
          "birth" : "1981/05/18",
          "describe" : "王者荣耀策划师",
          "phone" : 13517946268
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "8",
        "_score" : 1.0,
        "_source" : {
          "name" : "柯莉堃",
          "age" : 12,
          "birth" : "2008/04/05",
          "describe" : "我也叫柯莉堃",
          "phone" : 18115974684
        }
      }
    ]
  },
  "aggregations" : {
    "agg" : {
      "value" : 7
    }
  }
}
统计某字段的个数

相同字段的内容,也分开计数

GET /persion/_search
{
  "aggs": {
    "agg": {
      "value_count": {
        "field": "name"
      }
    }
  }
}
############ 结果 #############
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 8,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "柯莉堃",
          "age" : 24,
          "birth" : "1997/04/17",
          "describe" : "我是柯莉堃啊",
          "phone" : 18946297416
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : "刘德华",
          "age" : 60,
          "birth" : "1973/01/12",
          "describe" : "天王华仔",
          "phone" : 15179461347
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "name" : "肖战",
          "age" : 25,
          "birth" : "1996/03/15",
          "describe" : "招黑体质",
          "phone" : 13594462687
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.0,
        "_source" : {
          "name" : "王宝强",
          "age" : 55,
          "birth" : "1979/05/18",
          "describe" : "无敌绿巨人",
          "phone" : 18849532476
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "6",
        "_score" : 1.0,
        "_source" : {
          "name" : "上官婉儿",
          "age" : 18,
          "birth" : "2002/02/02",
          "describe" : "我不是一个法师",
          "phone" : 15174692184
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "7",
        "_score" : 1.0,
        "_source" : {
          "name" : "关羽",
          "age" : 65,
          "birth" : "1961/04/04",
          "describe" : "我不是历史的关羽",
          "phone" : 13579642589
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.0,
        "_source" : {
          "name" : "关菲菲",
          "age" : 50,
          "birth" : "1981/05/18",
          "describe" : "王者荣耀策划师",
          "phone" : 13517946268
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "8",
        "_score" : 1.0,
        "_source" : {
          "name" : "柯莉堃",
          "age" : 12,
          "birth" : "2008/04/05",
          "describe" : "我也叫柯莉堃",
          "phone" : 18115974684
        }
      }
    ]
  },
  "aggregations" : {
    "agg" : {
      "value" : 8
    }
  }
}
累加

把数值类型的数加起来。

GET /persion/_search
{
  "aggs": {
    "agg": {
      "sum": {
        "field": "age"
      }
    }
  }
}
########## 结果 ##########
"aggregations" : {
    "agg" : {
      "value" : 309.0
    }
  }
分组统计:

根据字段内容的相同,来统计个数。

GET /persion/_search
{
  "aggs": {
    "group": {
      "terms": {
        "field": "name",
        "order": {
          "_count": "desc"   #输出结果根据统计个数排序
        }
      }
    }
  }
}

############ 结果 ##############
{
  "took" : 4,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 8,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "柯莉堃",
          "age" : 24,
          "birth" : "1997/04/17",
          "describe" : "我是柯莉堃啊",
          "phone" : 18946297416
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : "刘德华",
          "age" : 60,
          "birth" : "1973/01/12",
          "describe" : "天王华仔",
          "phone" : 15179461347
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "name" : "肖战",
          "age" : 25,
          "birth" : "1996/03/15",
          "describe" : "招黑体质",
          "phone" : 13594462687
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.0,
        "_source" : {
          "name" : "王宝强",
          "age" : 55,
          "birth" : "1979/05/18",
          "describe" : "无敌绿巨人",
          "phone" : 18849532476
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "6",
        "_score" : 1.0,
        "_source" : {
          "name" : "上官婉儿",
          "age" : 18,
          "birth" : "2002/02/02",
          "describe" : "我不是一个法师",
          "phone" : 15174692184
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "7",
        "_score" : 1.0,
        "_source" : {
          "name" : "关羽",
          "age" : 65,
          "birth" : "1961/04/04",
          "describe" : "我不是历史的关羽",
          "phone" : 13579642589
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.0,
        "_source" : {
          "name" : "关菲菲",
          "age" : 50,
          "birth" : "1981/05/18",
          "describe" : "王者荣耀策划师",
          "phone" : 13517946268
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "8",
        "_score" : 1.0,
        "_source" : {
          "name" : "柯莉堃",
          "age" : 12,
          "birth" : "2008/04/05",
          "describe" : "我也叫柯莉堃",
          "phone" : 18115974684
        }
      }
    ]
  },
  "aggregations" : {
    "group" : {
      "doc_count_error_upper_bound" : 0,
      "sum_other_doc_count" : 0,
      "buckets" : [
        {
          "key" : "柯莉堃",
          "doc_count" : 2
        },
        {
          "key" : "上官婉儿",
          "doc_count" : 1
        },
        {
          "key" : "关羽",
          "doc_count" : 1
        },
        {
          "key" : "关菲菲",
          "doc_count" : 1
        },
        {
          "key" : "刘德华",
          "doc_count" : 1
        },
        {
          "key" : "王宝强",
          "doc_count" : 1
        },
        {
          "key" : "肖战",
          "doc_count" : 1
        }
      ]
    }
  }
}
范围统计

根据一个数值字段的范围统计个数。

#数值范围统计
GET /persion/_search
{
  "aggs": {
    "agg": {
      "range": {
        "field": "age",   #需要进行统计的字段
        "ranges": [
          {
            "to":10      #从最小的到10},
          {
            "from": 10,   #从10岁,包含10"to": 30      #到30岁,不包含30},
          {
          	"from":30     #从30到最大的
          }
        ]
      }
    }
  }
}

#时间范围统计
GET /persion/_search
{
  "aggs": {
    "agg": {
       "date_range": {
         "field": "birth",
         "format": "yyyy",   #格式化时间字段
         "ranges": [
           {
             "from": "1996",
             "to": "2003"
           }
         ]
       }
      }
    }
  }
统计聚合查询

也就是统计各种数据,比如最大值,平均值啥的。

GET /persion/_search
{
  "aggs": {
    "agg": {
      "extended_stats": {
        "field": "age"
      }
    }
  }
}
############ 结果 ##########
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 8,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "name" : "柯莉堃",
          "age" : 24,
          "birth" : "1997/04/17",
          "describe" : "我是柯莉堃啊",
          "phone" : 18946297416
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "2",
        "_score" : 1.0,
        "_source" : {
          "name" : "刘德华",
          "age" : 60,
          "birth" : "1973/01/12",
          "describe" : "天王华仔",
          "phone" : 15179461347
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "name" : "肖战",
          "age" : 25,
          "birth" : "1996/03/15",
          "describe" : "招黑体质",
          "phone" : 13594462687
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "5",
        "_score" : 1.0,
        "_source" : {
          "name" : "王宝强",
          "age" : 55,
          "birth" : "1979/05/18",
          "describe" : "无敌绿巨人",
          "phone" : 18849532476
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "6",
        "_score" : 1.0,
        "_source" : {
          "name" : "上官婉儿",
          "age" : 18,
          "birth" : "2002/02/02",
          "describe" : "我不是一个法师",
          "phone" : 15174692184
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "7",
        "_score" : 1.0,
        "_source" : {
          "name" : "关羽",
          "age" : 65,
          "birth" : "1961/04/04",
          "describe" : "我不是历史的关羽",
          "phone" : 13579642589
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "4",
        "_score" : 1.0,
        "_source" : {
          "name" : "关菲菲",
          "age" : 50,
          "birth" : "1981/05/18",
          "describe" : "王者荣耀策划师",
          "phone" : 13517946268
        }
      },
      {
        "_index" : "persion",
        "_type" : "_doc",
        "_id" : "8",
        "_score" : 1.0,
        "_source" : {
          "name" : "柯莉堃",
          "age" : 12,
          "birth" : "2008/04/05",
          "describe" : "我也叫柯莉堃",
          "phone" : 18115974684
        }
      }
    ]
  },
  "aggregations" : {
    "agg" : {
      "count" : 8,
      "min" : 12.0,
      "max" : 65.0,
      "avg" : 38.625,
      "sum" : 309.0,
      "sum_of_squares" : 15019.0,
      "variance" : 385.484375,
      "variance_population" : 385.484375,
      "variance_sampling" : 440.55357142857144,
      "std_deviation" : 19.633756008466644,
      "std_deviation_population" : 19.633756008466644,
      "std_deviation_sampling" : 20.98936805691328,
      "std_deviation_bounds" : {
        "upper" : 77.8925120169333,
        "lower" : -0.6425120169332885,
        "upper_population" : 77.8925120169333,
        "lower_population" : -0.6425120169332885,
        "upper_sampling" : 80.60373611382656,
        "lower_sampling" : -3.3537361138265567
      }
    }
  }
}

20._cat命令

_cat可以查看es的各种信息。

查看索引信息
GET /_cat/indices   #查看所有索引信息

GET /_cat/indices/索引名?v #查看指定索引信息

GET /_cat/allocation?v #查看资源情况

7.filter查询操作:

filter的查询操作跟query查询操作类似;但是filter查询操作不会计算分数,并且查询结果会缓存下来.

GET hello/_search
{
  "post_filter": {   //filter查询
    "match_all" : {} //查询类型
  }
}

8.script脚本:

es可以指定脚本来操作数据

"script": {
	"lang":   "...",             //指定脚本语言
	"source" | "id": "...",      //脚本语句
	"params": { ... }            //参数
}
POST hello/_update_by_query
{
  "query" : {
    "term" : {
      "name" : "哆啦A梦"
    }
  },
  "script": {
    "lang": "painless",
    "source": "ctx._source.count = params.count",
    "params": {"count" : 500}
  }
}

GET hello/_search
{
  "query": {
    "match_all" : {}
  },
  "_source": ["name","age"], 
  "script_fields": {
    "type": {
      "script": {
        "lang": "painless",
        "source": "if(doc['age'].value > 3){1}"
      }
    }
  }
}

11.java操作es(RestHighLevelClient)

1.创建操作es的客户端

//创建es客户端
   RestHighLevelClient client;

   @Before
   public void init(){
       HttpHost httpHost = new HttpHost("192.168.2.102",9200);
       RestClientBuilder clientBuilder = RestClient.builder(httpHost);
       client = new RestHighLevelClient(clientBuilder);
       System.out.println("init执行");
   }

   @After
   public void destroy() throws IOException {
       client.close();
       System.out.println("关闭资源");
   }

2.操作索引

1.创建索引

@Test
  public void createIndex() throws IOException {
       //设置索引
       Settings.Builder setting = Settings.builder();
       //设置索引分片数
       setting.put("number_of_shards", 2);
       //设置索引备份数
       setting.put("number_of_replicas", 1);

       //设置索引的mapping
       XContentBuilder mapping = JsonXContent.contentBuilder();
       mapping.startObject()

                   .startObject("properties")

                       .startObject("name")
                           .field("type", "text")
                       .endObject()

                       .startObject("age")
                           .field("type", "integer")
                       .endObject()

                       .startObject("birth")
                           .field("type","date")
                           .field("format", "yyyy-MM-dd")
                       .endObject()

                   .endObject()

               .endObject();
       //将setting和mapping封装到一个request对象中
       CreateIndexRequest createIndexRequest = new CreateIndexRequest("persion_01");
       createIndexRequest.settings(setting);
       createIndexRequest.mapping(mapping);

       //通过客户端发送请求给服务端
       CreateIndexResponse response = client.indices().create(createIndexRequest, RequestOptions.DEFAULT);
       System.out.println(response);
   }

2.删除索引

@Test
   public void deleteIndex() throws IOException {
       DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("persion_01");
       AcknowledgedResponse response = client.indices().delete(deleteIndexRequest, RequestOptions.DEFAULT);
       System.out.println(response);
   }

3.得到索引

@Test
   public void getIndex() throws IOException {
       GetIndexRequest getIndexRequest = new GetIndexRequest("book");
       boolean exists = client.indices().exists(getIndexRequest, RequestOptions.DEFAULT);
       System.out.println(exists);
   }

3.操作文档

1.创建文档

@Test
   public void createDoc() throws IOException {
       Book book = new Book("火影", 00000001L);
       //创建一个json转换类
       ObjectMapper mapper = new JsonMapper();
       //将Book对象转换成json数据
       String json = mapper.writeValueAsString(book);
       //创建一个请求
       IndexRequest request = new IndexRequest();
       request.index("book").id("3");
       request.source(json, XContentType.JSON);

       client.index(request, RequestOptions.DEFAULT);
   }

2.修改文档

@Test
   public void updateDoc() throws IOException {
       Map<String,Object> map = new HashMap<>();
       map.put("name", "火影忍者");

       UpdateRequest updateRequest = new UpdateRequest("book","3");
       updateRequest.doc(map);

       client.update(updateRequest, RequestOptions.DEFAULT);
   }

3.删除文档

@Test
   public void deleteDoc() throws IOException {
       DeleteRequest request = new DeleteRequest("book");
       request.id("3");
       client.delete(request, RequestOptions.DEFAULT);
   }

4.批量增加

@Test
   public void bulkDoc() throws IOException {
       Book book = new Book("西游记", 2L);
       Book book1 = new Book("水浒传", 1L);
       Book book2 = new Book("红楼梦", 3L);

       ObjectMapper mapper = new ObjectMapper();
       String json = mapper.writeValueAsString(book);
       String json1 =mapper.writeValueAsString(book1);
       String json2 =mapper.writeValueAsString(book2);

       //批量添加文件
       BulkRequest request = new BulkRequest();
       request.add(new IndexRequest("book").source(json, XContentType.JSON));
       request.add(new IndexRequest("book").source(json1, XContentType.JSON));
       request.add(new IndexRequest("book").source(json2, XContentType.JSON));

       client.bulk(request, RequestOptions.DEFAULT);
   }

5.批量删除

@Test
  public void bulkDeleteDoc() throws IOException {
      BulkRequest request = new BulkRequest();
      request.add(new DeleteRequest("book","qN4Jq3cBZMG8vJ7fnene"));
      request.add(new DeleteRequest("book","qd4Jq3cBZMG8vJ7fnene"));
      request.add(new DeleteRequest("book","qt4Jq3cBZMG8vJ7fnene"));
      client.bulk(request, RequestOptions.DEFAULT);
  }

4.查询操作

1.term查询

@Test
    public void termQuery() throws IOException {
        //创建搜索请求,并指定索引
        SearchRequest request = new SearchRequest("persion");

        //指定查询条件
        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.from(0).size(3);
        builder.query(QueryBuilders.termQuery("name", "柯莉堃"));

        //把查询条件加入搜索请求中
        request.source(builder);

        //执行查询
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        for (SearchHit hit : response.getHits().getHits()) {
            Map<String, Object> data = hit.getSourceAsMap();
            System.out.println(data);
        }
    }

2.terms查询

@Test
   public void termsQuery() throws IOException {
       SearchRequest request = new SearchRequest("persion");

       SearchSourceBuilder builder = new SearchSourceBuilder();
       builder.from(0).size(3);
       builder.query(QueryBuilders.termsQuery("name","刘德华","肖战","王宝强"));

       request.source(builder);

       SearchResponse response = client.search(request, RequestOptions.DEFAULT);
       for (SearchHit hit : response.getHits()) {
           Map<String, Object> data = hit.getSourceAsMap();
           System.out.println(data);
       }
   }

3.match查询

@Test
   public void matchQuery() throws IOException {
       SearchRequest request = new SearchRequest("persion");

       SearchSourceBuilder builder = new SearchSourceBuilder();
       builder.from(0).size(3);
       builder.query(QueryBuilders.matchQuery("describe", "不是"));

       request.source(builder);

       SearchResponse response = client.search(request, RequestOptions.DEFAULT);
       for (SearchHit hit : response.getHits()) {
           Map<String, Object> data = hit.getSourceAsMap();
           System.out.println(data);
       }

   }

4.match_all查询

@Test
   public void match_allQuery() throws IOException {
       SearchRequest request = new SearchRequest("persion");

       SearchSourceBuilder builder = new SearchSourceBuilder();
       builder.query(QueryBuilders.matchAllQuery());

       request.source(builder);

       SearchResponse response = client.search(request, RequestOptions.DEFAULT);
       for (SearchHit hit : response.getHits()) {
           Map<String, Object> data = hit.getSourceAsMap();
           System.out.println(data);
       }
   }

5.matchbool查询

@Test
   public void matchBoolQuery() throws IOException {
       SearchRequest request = new SearchRequest("persion");

       SearchSourceBuilder builder = new SearchSourceBuilder();
       builder.query(QueryBuilders.matchQuery("describe", "不是 历史").operator(Operator.AND));

       request.source(builder);

       SearchResponse response = client.search(request, RequestOptions.DEFAULT);
       for (SearchHit hit : response.getHits()) {
           Map<String, Object> data = hit.getSourceAsMap();
           System.out.println(data);
       }
   }

6.mulit_match查询

@Test
    public void mulitMatchQuery() throws IOException {
        SearchRequest request = new SearchRequest("persion");

        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.multiMatchQuery("柯莉堃","name"));

        request.source(builder);

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        for (SearchHit hit : response.getHits()) {
            Map<String, Object> data = hit.getSourceAsMap();
            System.out.println(data);
        }
    }

7.id查询

@Test
    public void idQuery() throws IOException {
        GetRequest request = new GetRequest("persion", "1");
        GetResponse response = client.get(request, RequestOptions.DEFAULT);
        System.out.println(response.getSourceAsMap());
    }

8.ids查询

@Test
    public void idsQuery() throws IOException {
        SearchRequest request = new SearchRequest("persion");

        SearchSourceBuilder builder = new SearchSourceBuilder();
        builder.query(QueryBuilders.idsQuery().addIds("1","2","3"));

        request.source(builder);

        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        for (SearchHit hit : response.getHits()) {
            Map<String, Object> data = hit.getSourceAsMap();
            System.out.println(data);
        }
    }

9.scroll查询

@Test
public void scrollQuery() throws IOException {
    //1.创建搜索请求
    SearchRequest request = new SearchRequest("persion");
    //2.指定scroll
    request.scroll(new TimeValue(1L));

    //3.指定查询条件
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.size(2);
    builder.sort("age", SortOrder.ASC);
    builder.query(QueryBuilders.matchAllQuery());

    request.source(builder);

    //4.查询首页
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    for (SearchHit hit : response.getHits()) {
        Map<String, Object> data = hit.getSourceAsMap();
        System.out.println(data);
    }

    //5.得到scroll_id
    String id = response.getScrollId();

    //6.循环读取下一页
    while (true){
        SearchScrollRequest request1 = new SearchScrollRequest(id);

        //7.指定scroll时间
        request1.scroll(new TimeValue(1L));

        //8.执行请求
        SearchResponse response1 = client.scroll(request1, RequestOptions.DEFAULT);

        //9.获取数据
        SearchHit[] hits = response1.getHits().getHits();

        //10.判断提出条件
        if (hits == null || hits.length == 0){
            break;
        }

        //11.取出数据
        for (SearchHit hit : hits) {
            Map<String, Object> data = hit.getSourceAsMap();
            System.out.println(data);
        }
    }
    //12.删除scroll
    ClearScrollRequest clearScrollRequest = new ClearScrollRequest();
    clearScrollRequest.addScrollId(id);

    client.clearScroll(clearScrollRequest, RequestOptions.DEFAULT);
}

10.delete_by_query删除

@Test
    public void deleteByQuery() throws IOException {
        DeleteByQueryRequest request = new DeleteByQueryRequest("persion");
        request.setQuery(QueryBuilders.termsQuery("name", "王宝强"));
        client.deleteByQuery(request, RequestOptions.DEFAULT);
    }

11.bool查询

@Test
 public void boolQuery() throws IOException {
     SearchRequest request = new SearchRequest("persion");

     SearchSourceBuilder builder = new SearchSourceBuilder();
     BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
     boolQueryBuilder.must(QueryBuilders.termsQuery("name", "柯莉堃","刘德华","关菲菲"));
     boolQueryBuilder.should(QueryBuilders.matchQuery("describe", "体质"));
     boolQueryBuilder.filter(QueryBuilders.rangeQuery("age").gt("20").lt("30"));
     builder.query(boolQueryBuilder);
     request.source(builder);

     SearchResponse response = client.search(request, RequestOptions.DEFAULT);
     for (SearchHit hit : response.getHits()) {
         Map<String, Object> data = hit.getSourceAsMap();
         System.out.println(data);
     }
 }

12.boosting查询

@Test
 public void boostingQuery() throws IOException {
     SearchRequest request = new SearchRequest("persion");

     SearchSourceBuilder builder = new SearchSourceBuilder();
     BoostingQueryBuilder boostingQueryBuilder = new BoostingQueryBuilder(
             QueryBuilders.termsQuery("name", "柯莉堃","肖战","刘德华"),
             QueryBuilders.matchQuery("describe", "体质")
     ).negativeBoost(0.5F);
     builder.query(boostingQueryBuilder);
     request.source(builder);

     SearchResponse response = client.search(request, RequestOptions.DEFAULT);
     for (SearchHit hit : response.getHits()) {
         Map<String, Object> data = hit.getSourceAsMap();
         System.out.println(data);
     }
 }

13.highlight查询

@Test
public void highLightQuery() throws IOException {
    SearchRequest request = new SearchRequest("persion");
    SearchSourceBuilder builder = new SearchSourceBuilder();
    builder.query(QueryBuilders.matchQuery("describe", "体质"));

    HighlightBuilder highlightBuilder = new HighlightBuilder();
    highlightBuilder.field("describe")
            .fragmentSize(10)
            .preTags("<front color='red'>")
            .postTags("</front>");

    builder.highlighter(highlightBuilder);

    request.source(builder);

    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    SearchHit[] hits = response.getHits().getHits();
    for (SearchHit hit : hits) {
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();
        Text[] fragments = highlightFields.get("describe").getFragments();
        for (Text fragment : fragments) {
            System.out.println(fragment.string());
        }
    }
}

14.aggs查询

去重统计
@Test
 public void aggsQuery() throws IOException {
     SearchRequest request = new SearchRequest("persion");

     SearchSourceBuilder builder = new SearchSourceBuilder();
     //指定agg查询,并设置查询名称
     builder.aggregation(AggregationBuilders.cardinality("agg").field("name"));

     request.source(builder);

     SearchResponse response = client.search(request, RequestOptions.DEFAULT);
     Cardinality agg = response.getAggregations().get("agg");
     System.out.println(agg.getValue());
 }
 
聚合统计
@Test
public void aggsextendsStates() throws IOException {
    SearchRequest request = new SearchRequest("persion");

    SearchSourceBuilder builder = new SearchSourceBuilder();
    //指定agg查询,并设置查询名称
    builder.aggregation(AggregationBuilders.extendedStats("agg").field("age"));

    request.source(builder);

    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    ExtendedStats agg = response.getAggregations().get("agg");
    System.out.println(agg.getMax());
    System.out.println(agg.getSum());
}

12.java操作es(ElasticsearchClient)

在es7.15版本,RestHighLevelClient已经被弃用了,改用ElasticsearchClient

maven :

<dependency>
   <groupId>co.elastic.clients</groupId>
   <artifactId>elasticsearch-java</artifactId>
   <version>7.17.8</version>
 </dependency>

 <dependency>
   <groupId>com.fasterxml.jackson.core</groupId>
   <artifactId>jackson-databind</artifactId>
   <version>2.12.3</version>
 </dependency>

	lf you get ClassNotFoundException: jakarta.json.spi.JsonProvider
	<dependency>
   <groupId>jakarta.json</groupId>
   <artifactId>jakarta.json-api</artifactId>
   <version>2.0.1</version>
 </dependency>

官网

1.创建客户端:

@Configuration
public class MyConfig {

    @Bean
    public ElasticsearchClient esClient() {
        RestClient client = RestClient.builder(new HttpHost("localhost", 9200)).build();
        ElasticsearchTransport transport = new RestClientTransport(client, new JacksonJsonpMapper());
        return new ElasticsearchClient(transport);
    }

}

测试客户端是否连接成功:

@Autowired
private ElasticsearchClient esClient;

@Test
void contextLoads() throws IOException {
    BooleanResponse ping = esClient.ping();
    System.out.println(ping.value());
}

2.操作索引:

1.添加索引:

@Autowired
private ElasticsearchClient esClient;

@Test
void contextLoads() throws IOException {
    CreateIndexResponse createIndexResponse = esClient.indices().create(i -> i
            .index("haha")  //指定索引名称
            .aliases("my_haha", new Alias.Builder().isWriteIndex(true).build()) //指定索引别名
            .settings(s -> s.index(set -> set
                            .numberOfShards("2")    //指定分片数量
                            .numberOfReplicas("1") //指定备份分片数
                    )
            )  //指定setting
            .mappings(m -> m
                    .dynamic(DynamicMapping.Strict)  //指定动态映射的模式
                    .properties("name", p -> p.keyword(KeywordProperty.of(t -> t.ignoreAbove(10))))   //设置属性
                    .properties("describe", Property.of(t -> t.text(set -> set.analyzer("ik_max_word")))) //设置属性
                    .properties("count", p -> p.integer(set -> set)) //设置属性
            ) //指定映射
    );
    System.out.println(createIndexResponse.acknowledged()); //告知
}

2.删除索引:

@Test
void test() throws IOException {
    DeleteIndexResponse deleteIndexResponse = esClient.indices().delete(i -> i.index("idx"));
    System.out.println(deleteIndexResponse.acknowledged());
}

3.获取索引:

//判断索引是否存在
@Test
void test01() throws IOException {
    BooleanResponse booleanResponse = esClient.indices().exists(i -> i.index("hello"));
    System.out.println(booleanResponse.value());
}

//得到索引
@Test
void test02() throws IOException {
    GetIndexResponse getIndexResponse = esClient.indices().get(i -> i.index("hello"));
    System.out.println(getIndexResponse.result());
}

4.修改索引:

@Test
void test03() throws IOException {
    //修改setting
    PutIndicesSettingsResponse putIndicesSettingsResponse = esClient.indices().putSettings(i -> i.index("hello").settings(set -> set.numberOfReplicas("0")));
    //增加mapping-properties字段
    PutMappingResponse putMappingResponse = esClient.indices().putMapping(i -> i.index("hello").properties("age", set -> set.integer(s -> s)));
    //修改别名
    DeleteAliasResponse deleteAliasResponse = esClient.indices().deleteAlias(i -> i.index("hello").name("my_hello"));
    //添加别名
    PutAliasResponse putAliasResponse = esClient.indices().putAlias(i -> i.index("hello").name("my_hello").isWriteIndex(true));
}

3.操作文档:

1.添加文档:

//仅仅只能添加文档,如果文档id已经存在,则会报错
@Test
void test05() throws IOException {
    Map<String, Object> map = new HashMap<>();
    map.put("name", "哆啦A梦");
    map.put("age", "16");
    CreateResponse createResponse = esClient.create(i -> i.index("hello").type("_doc").id("2").document(map));
    System.out.println(createResponse.result().jsonValue());
}

//添加文档,如果文档id存在,则直接覆盖
@Test
void test04() throws IOException {
    Map<String, Object> map = new HashMap<>();
    map.put("name", "哆啦A梦");
    map.put("age", "16");
    IndexResponse indexResponse = esClient.index(i -> i.index("hello").type("_doc").id("2").document(map));
    System.out.println(indexResponse.result().jsonValue());
}

2.修改文档:

//仅仅是修改文档,修改成功返回Updated,修改失败返回NoOp(没有选项呗修改)
@Test
void test06() throws IOException {
    Map<String, Object> map = new HashMap<>();
    map.put("name", "哆啦A梦");
    map.put("age", "5");
    UpdateResponse<Map> updateResponse = esClient.update(i -> i.index("hello").type("_doc").id("2").doc(map), Map.class);
    System.out.println(updateResponse.result());
}

3.删除文档:

@Test
void test07() throws IOException {
    DeleteResponse deleteResponse = esClient.delete(i -> i.index("class").type("_doc").id("1"));
    System.out.println(deleteResponse.result());
}

4.批量增加:

@Test
void test08() throws IOException {
    Map<String, Object> map = new HashMap<>();
    map.put("name", "哆啦A梦");
    map.put("age", "5");
    List<BulkOperation> list = new ArrayList<>();
    list.add(BulkOperation.of(o -> o.index(d -> d.index("hello").id("3").document(map))));
    list.add(BulkOperation.of(o -> o.index(d -> d.index("hello").id("4").document(map))));
    list.add(BulkOperation.of(o -> o.index(d -> d.index("hello").id("5").document(map))));
    BulkResponse bulkResponse = esClient.bulk(i -> i.operations(list));
    System.out.println(bulkResponse.errors());
}

5.批量删除:

@Test
void test09() throws IOException {
    List<BulkOperation> list = new ArrayList<>();
    list.add(BulkOperation.of(o -> o.delete(d -> d.index("hello").id("3"))));
    list.add(BulkOperation.of(o -> o.delete(d -> d.index("hello").id("4"))));
    list.add(BulkOperation.of(o -> o.delete(d -> d.index("hello").id("5"))));
    BulkResponse bulkResponse = esClient.bulk(i -> i.operations(list));
    System.out.println(bulkResponse.items());
}

4.查询操作:

1.term查询:

@Test
void test10() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i.index("class").query(s -> s.term(p -> p.field("name").value("火箭"))), Map.class);
    for (Hit<Map> hit : searchResponse.hits().hits()) {  //遍历击中的每条数据
        System.out.println(hit.source());
    }
}

2.terms查询:

	//某列查询多值,or关系
@Test
   void test11() throws IOException {
       List<FieldValue> list = new ArrayList<>();
       list.add(FieldValue.of("蜡笔小新"));
       list.add(FieldValue.of("哆啦A梦"));
       SearchResponse<Map> searchResponse = esClient.search(i -> i
                       .index("hello")
                       .query(q -> q.terms(t -> t.terms(v -> v.value(list)).field("name")))
               , Map.class);
       for (Hit<Map> hit : searchResponse.hits().hits()) {
           System.out.println(hit.source());
       }
   }

3.match查询:

   @Test
   void test12() throws IOException {
       SearchResponse<Map> searchResponse = esClient.search(i -> i
                       .index("class")
                       .query(q -> q.match(m -> m.field("describe").query("火箭")))
               , Map.class);
       for (Hit<Map> hit : searchResponse.hits().hits()) {
           System.out.println(hit.source());
       }
   }

//match多值查询
   @Test
   void test12() throws IOException {
       SearchResponse<Map> searchResponse = esClient.search(i -> i
                       .index("class")
                       .query(q -> q.match(m -> m.field("describe").query("火箭 希望")))
               , Map.class);
       for (Hit<Map> hit : searchResponse.hits().hits()) {
           System.out.println(hit.source());
       }
   }

4.match_all查询:

@Test
void test13() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i
                    .index("class")
                    .query(q -> q.matchAll(m -> m.boost(1.2f)))
            , Map.class);
    for (Hit<Map> hit : searchResponse.hits().hits()) {
        System.out.println(hit.source());
        System.out.println(hit.score());
    }
}

5.multi_match查询:

@Test
void test13() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i
                    .index("class")
                    .query(q -> q.multiMatch(m -> m.query("希望 梦幻").fields("name","describe")))
            , Map.class);
    for (Hit<Map> hit : searchResponse.hits().hits()) {
        System.out.println(hit.source());
    }
}

6.id查询:

@Test
void test14() throws IOException {
    GetResponse<Map> getResponse = esClient.get(i -> i.index("class").type("_doc").id("5"), Map.class);
    Map source = getResponse.source();
    System.out.println(source);
}

7.ids查询:

@Test
void test13() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i
                    .index("class")
                    .query(q -> q.ids(s -> s.values("4","5")))
            , Map.class);
    for (Hit<Map> hit : searchResponse.hits().hits()) {
        System.out.println(hit.source());
    }
}

8.prefix查询:

@Test
void test13() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i
                    .index("class")
                    .query(q -> q.prefix(p -> p.field("name").value("火")))
            , Map.class);
    for (Hit<Map> hit : searchResponse.hits().hits()) {
        System.out.println(hit.source());
    }
}

9.fuzzy查询:

@Test
void test13() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i
                    .index("class")
                    .query(q -> q.fuzzy(f -> f.field("name").value("湖贝大学").fuzziness("auto")))
            , Map.class);
    for (Hit<Map> hit : searchResponse.hits().hits()) {
        System.out.println(hit.source());
    }
}

10.wildcard查询:

@Test    
void test13() throws IOException {
        SearchResponse<Map> searchResponse = esClient.search(i -> i
                        .index("class")
                        .query(q -> q.wildcard(w -> w.field("name").value("湖*")))
                , Map.class);
        for (Hit<Map> hit : searchResponse.hits().hits()) {
            System.out.println(hit.source());
        }
    }

11.range查询:

@Test
void test13() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i
                    .index("hello")
                    .query(q -> q.range(r -> r.field("age").gte(JsonData.of(4)).lte(JsonData.of(20))))
            , Map.class);
    for (Hit<Map> hit : searchResponse.hits().hits()) {
        System.out.println(hit.source());
    }
}

12.regexp查询:

@Test
void test13() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i
                    .index("hello")
                    .query(q -> q.regexp(r -> r.field("name").value(".*A.")))
            , Map.class);
    for (Hit<Map> hit : searchResponse.hits().hits()) {
        System.out.println(hit.source());
    }
}

13.scroll查询:

   //第一次查询
@Test
   void test15() throws IOException {
       SearchResponse<Map> searchResponse = esClient.search(s -> s
                       .index("class")
                       .scroll(Time.of(t -> t.time("5m")))
                       .query(q -> q.matchAll(m -> m))
                       .size(2)
               , Map.class);
       for (Hit<Map> hit : searchResponse.hits().hits()) {
           System.out.println(hit.source());
       }
       System.out.println(searchResponse.scrollId());
   }

//第二次查询
@Test
   void test16() throws IOException {
       SearchResponse<Map> searchResponse = esClient.scroll(s -> s
                       .scroll(Time.of(t -> t.time("5m")))                      		  .scrollId("FGluY2x1ZGVfY29udGV4dF91dWlkDXF1ZXJ5QW5kRmV0Y2gBFlhJN1pJbjNDUkVtNGI3RFppdlNqZFEAAAAAAAAChBY3eE9taUJ4b1JtNm5tcU84bkxCeW93")
                       .scroll(Time.of(t -> t.time("1m")))
               , Map.class);
       for (Hit<Map> hit : searchResponse.hits().hits()) {
           System.out.println(hit.source());
       }
   }

14._delete_by_query查询删除:

@Test
void test17() throws IOException {
    DeleteByQueryResponse deleteByQueryResponse = esClient.deleteByQuery(q -> q
            .index("class")
            .query(s -> s
                    .term(t -> t
                            .field("name")
                            .value("一班")
                    )
            )
    );
    System.out.println(deleteByQueryResponse.deleted());
}

15._update_by_query查询修改:

@Test
   void test18() throws IOException {
       UpdateByQueryResponse updateByQueryResponse = esClient.updateByQuery(i -> i
               .index("hello")  //指定索引
               .query(q -> q   //指定查询操作
                       .term(t -> t
                               .field("name")
                               .value("哆啦A梦")
                       )
               )
               .script(s -> s   //指定脚本
                       .inline(l -> l
                               .lang("painless")  //指定脚本语言
                               .source("ctx._source.count = params.c")  //脚本语句
                               .params("c", JsonData.of(1000))  //参数
                       )
               )
       );
       System.out.println(updateByQueryResponse.updated());
   }

16.bool查询:

@Test
void test13() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i
                    .index("class")
                    .query(q -> q
                            .bool(b -> b
                                    .must(m -> m
                                            .match(t -> t
                                                    .field("describe")
                                                    .query("葵花 希望")
                                            )
                                    )
                                    .should(s -> s
                                            .term(t -> t
                                                    .field("name")
                                                    .value("火箭")
                                            )
                                    )
                            )
                    )
            , Map.class);
    for (Hit<Map> hit : searchResponse.hits().hits()) {
        System.out.println(hit.source());
    }
}

17.boosting查询:

@Test
void test13() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i
                    .index("class")
                    .query(q -> q.boosting(b -> b
                                    .positive(p -> p
                                            .match(m -> m
                                                    .field("describe")
                                                    .query("葵花 希望")
                                            )
                                    )
                                    .negative(n -> n
                                            .term(t -> t
                                                    .field("name")
                                                    .value("火箭")
                                            )
                                    )
                                    .negativeBoost(0.2d)
                            )
                    )
            , Map.class);
    for (Hit<Map> hit : searchResponse.hits().hits()) {
        System.out.println(hit.score());
        System.out.println(hit.source());
    }
}

18.highlight查询:

@Test
void test13() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i
                    .index("class")
                    .query(q -> q.match(m -> m.field("describe").query("葵花 希望")))
                    .highlight(h -> h.fields("describe",
                            l -> l.preTags("<span color='red'>").postTags("</span>")))
            , Map.class);
    for (Hit<Map> hit : searchResponse.hits().hits()) {
        System.out.println(hit.source());
        System.out.println(hit.highlight());
    }
}

19.分页查询:

@Test
void test12() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i  //搜索请求
                    .index("class")                        //索引
                    .query(q -> q.matchAll(m -> m))
                    .from(0)                                    //起始数据  
                    .size(3)                                    //页大小
            , Map.class);
    for (Hit<Map> hit : searchResponse.hits().hits()) {
        System.out.println(hit.source());
    }
}

20.排序查询:

@Test
void test12() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i  //搜索请求
                    .index("class")                        //索引
                    .query(q -> q.matchAll(m -> m))
                    .sort(s -> s.field(f -> f.field("code").order(SortOrder.Desc)))                                   //页大小
            , Map.class);
    for (Hit<Map> hit : searchResponse.hits().hits()) {
        System.out.println(hit.source());
    }
}

21.聚合查询:

查询数据数:
@Test
void test19() throws IOException {
    CountResponse countResponse = esClient.count(i -> i.index("class"));
    System.out.println(countResponse.count());
}
基数查询:
@Test
void test19() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i
                    .index("class")
                    .query(q -> q
                            .match(m -> m
                                    .field("describe")
                                    .query("葵花")
                            )
                    )
                    .aggregations("agg", a -> a.cardinality(c -> c.field("stu_count")))
            , Map.class);
    for (Map.Entry<String, Aggregate> entry : searchResponse.aggregations().entrySet()) {
        System.out.println(entry.getKey() + "=" + entry.getValue().cardinality().value());
    }
}
统计字段:
@Test
void test19() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i
                    .index("class")
                    .aggregations("agg", a -> a.valueCount(v -> v.field("stu_count")))
            , Map.class);
    for (Map.Entry<String, Aggregate> entry : searchResponse.aggregations().entrySet()) {
        System.out.println(entry.getKey() + "=" + entry.getValue().valueCount().value());
    }
}
累加:
@Test
void test19() throws IOException {
    SearchResponse<Map> searchResponse = esClient.search(i -> i
                    .index("class")
                    .aggregations("agg", a -> a.sum(s -> s.field("stu_count")))
            , Map.class);
    for (Map.Entry<String, Aggregate> entry : searchResponse.aggregations().entrySet()) {
        System.out.println(entry.getKey() + "=" + entry.getValue().sum().value());
    }
}
分组查询:
    void test19() throws IOException {
        Map<String, SortOrder> map = new HashMap<>();
        map.put("_count", SortOrder.Desc);
        SearchResponse<Map> searchResponse = esClient.search(i -> i
                        .index("hello")
                        .aggregations("agg", a -> a.terms(t -> t.field("name")))
                , Map.class);
        for (StringTermsBucket agg : searchResponse.aggregations().get("agg").sterms().buckets().array()) {
            System.out.println(agg.key() + "=" + agg.docCount());
        }
    }
//根据a.terms(t -> t.field("name")字段类型不同,返回的terms对象分为:
//sterms() ====> StringTermsBucket
//lterms() ====> LongTermsBucket
//dterms() ====> DoubleTermsBucket
范围查询:
@Test
void test19() throws IOException {
    Map<String, SortOrder> map = new HashMap<>();
    map.put("_count", SortOrder.Desc);
    SearchResponse<Map> searchResponse = esClient.search(i -> i
                    .index("hello")
                    .aggregations("agg", a -> a.range(r -> r
                            .field("age")
                            .ranges(s -> s.from("1").to("10"))))
            , Map.class);
    for (RangeBucket agg : searchResponse.aggregations().get("agg").range().buckets().array()) {
        System.out.println(agg.key() + "=" + agg.docCount());
    }
}
统计查询:
@Test
void test20() throws IOException {
    Map<String, SortOrder> map = new HashMap<>();
    map.put("_count", SortOrder.Desc);
    SearchResponse<Map> searchResponse = esClient.search(i -> i
                    .index("hello")
                    .aggregations("agg", a -> a.stats(s -> s.field("age")))
            , Map.class);
    StatsAggregate agg = searchResponse.aggregations().get("agg").stats();
    System.out.println(agg.max());
    System.out.println(agg.min());
    System.out.println(agg.sum());
    System.out.println(agg.avg());
    System.out.println(agg.count());
}

22.重建索引:

//重建索引
@Test
   void test22() throws IOException {
       Map<String, Property> map = new HashMap<>();
       map.put("name", Property.of(p -> p.keyword(k -> k.ignoreAbove(5))));
       map.put("describe", Property.of(p -> p.text(t -> t.analyzer("ik_max_word"))));
       map.put("age", Property.of(p -> p.integer(i -> i)));
       map.put("count", Property.of(p -> p.long_(l -> l)));
       CreateIndexResponse createIndexResponse = esClient.indices().create(i -> i
               .index("hellos")
               .settings(s -> s
                       .numberOfShards("1")
                       .numberOfReplicas("1")
               )
               .mappings(m -> m
                       .dynamic(DynamicMapping.Strict)
                       .properties(map)
               )
               .aliases("my_hellos", Alias.of(a -> a.isWriteIndex(true)))
       );
       System.out.println(createIndexResponse.acknowledged());
   }

//迁移数据
   @Test
   void test23() throws IOException {
       ReindexResponse reindexResponse = esClient.reindex(r -> r
               .source(s -> s.index("hello")   //源索引
               )
               .dest(d -> d.index("hellos"))  //目的索引
       );
       System.out.println(reindexResponse.batches());
   }

文章作者: 威@猫
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 威@猫 !
评论
  目录