5.1【客户端介绍】
官方文档地址: https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
实际开发中,有多种方式操作Elasticsearch:
客户端工具:发送http请求(RESTful**风格)操作:
使用Postman发送请求直接操作
使用ElasticSearch-head-master图形化界面插件操作
使用Elastic官方数据可视化的平台Kibana进行操作【推荐】
Java代码操作:**
Elasticsearch提供的Java API 客户端进行操作
Spring Data ElasticSearch 持久层框架进行操作
官网支持的客户端访问方式:
https://www.elastic.co/guide/en/elasticsearch/client/index.html
5.2【索引库操作】
使用Kibana进行以下实验,进行Restful接口访问
索引库操作,完成对索引的增、删、查操作
1. 创建索引库(index)
| 发送请求: |
|---|
| # 在kibana中,不用写地址和端口,/shopping是简化写法,真实请求地址是:http://127.0.0.1:9200/shopping # 请求方法:PUT PUT /shopping |
| 响应结果: |
| #! Deprecation: the default number of shards will change from [5] to [1] in 7.0.0; if you wish to continue using the default of [5] shards, you must manage this on the create index request or with an index template { “acknowledged” : true, “shards_acknowledged” : true, “index” : “shopping” } |
| “acknowledged” : true, 代表操作成功 “shards_acknowledged” : true, 代表分片操作成功 “index” : “shopping” 表示创建的索引库名称 注意:创建索引库的分片数默认5片,在7.0.0之后的ElasticSearch版本中,默认1片; |
| 重复添加:报错,已经存在 |
![]() |
2. 查看所有索引(index)
| 发送请求: |
|---|
| # 请求方法:GET GET /_cat/indices?v |
| 响应结果: |
![]() |
表头的含义(查看帮助信息:GET /_cat/indices?help)
| health | 当前服务器健康状态: green(集群完整) yellow(单点正常、集群不完整) red(单点不正常) |
|---|---|
| status | 索引打开、关闭状态 |
| index | 索引名 |
| uuid | 索引统一编号 |
| pri | 主分片数量 |
| rep | 副分片数量 |
| docs.count | 可用文档数量 |
| docs.deleted | 文档删除状态(逻辑删除,段合并时被清理) |
| store.size | 主分片和副分片整体占空间大小 |
| pri.store.size | 主分片占空间大小 |
3. 查看某个索引(index)
| 发送请求: |
|---|
| # 请求方法:GET GET /shopping |
| 响应结果: { “shopping” : { “aliases” : { }, “mappings” : { }, “settings” : { “index” : { “creation_date” : “1586587411462”, “number_of_shards” : “5”, “number_of_replicas” : “1”, “uuid” : “VCl1hHsJQDe2p2dn46o0NA”, “version” : { “created” : “6080199” }, “provided_name” : “shopping” } } } } 内容解释: { “shopping【索引库名】” : { “aliases【别名】” : { }, “mappings【映射】” : { }, “settings”【索引库设置】 : { “index【索引】” : { “creation_date【创建时间】” : “1586587411462”, “number_of_shards【索引库分片数】” : “5”, “number_of_replicas【索引库副本数】” : “1”, “uuid【唯一标识】” : “VCl1hHsJQDe2p2dn46o0NA”, “version【版本】” : { “created” : “6080199” }, “provided_name【索引库名称】” : “shopping” } } } } |
4. 删除索引(index)
| 发送请求: |
|---|
| # 请求方法:DELETE DELETE /shopping |
| 响应结果: |
| { “acknowledged” : true } |
5.3【类型及映射操作】
1. 创建类型映射
有了索引库,等于有了数据库中的database。
接下来就需要建索引库(index)中的类型(type)了,类似于数据库(database)中的表(table)。创建数据库表需要设置字段名称,类型,长度,约束等;索引库也一样,在创建索引库的类型时,需要知道这个类型下有哪些字段,每个字段有哪些约束信息,这就叫做映射(mapping)。
给shopping这个索引库添加了一个名为product的类型,并且在类型中设置了4个字段:
title:商品标题
subtitle: 商品子标题
images:商品图片
price:商品价格
| 发送请求: |
|---|
| # 请求方法:PUT PUT /shopping/product/_mapping { “properties”: { “title“:{ “type”: “text”, “analyzer”: “ik_max_word” }, “subtitle“:{ “type”: “text”, “analyzer”: “ik_max_word” }, “images“:{ “type”: “keyword”, “index”: false }, “price“:{ “type”: “float”, “index”: true } } } PUT /索引库名/_mapping/类型名称 或 索引库名/类型名称/_mapping { “properties”: { “字段名称”:{ “type【类型】”: “类型”, “index【是否索引】”: true, “store【是否存储】”: false, “analyzer【分词器】”: “具体分词器” } … } } |
| 响应结果: |
| #! Deprecation: [types removal] Specifying types in put mapping requests is deprecated. To be compatible with 7.0, the mapping definition should not be nested under the type name, and the parameter include_type_name must be provided and set to false. { “acknowledged” : true } |
| 说明: #! 弃用:[类型删除]不建议在放置映射请求中指定类型。 为了与7.0兼容,映射定义不应嵌套在类型名称下,并且必须提供参数include_type_name并将其设置为false。 |
l 类型名称:就是前面将的type的概念,类似于数据库中的表
l 字段名:任意填写,下面指定许多属性,例如:title、subtitle、images、price
type:类型
Elasticsearch中支持的数据类型非常丰富,说几个关键的:
①String类型,又分两种:
text:可分词
keyword:不可分词,数据会作为完整字段进行匹配
②Numerical:数值类型,分两类
基本数据类型:long、interger、short、byte、double、float、half_float
浮点数的高精度类型:scaled_float
③Date:日期类型
④Array:数组类型
⑤Object:对象
l index:是否索引,默认为**true,也就是说你不进行任何配置,所有字段都会被索引。
true:字段会被索引,则可以用来进行搜索
false:字段不会被索引,不能用来搜索
l store:是否将数据进行独立存储,默认为false
原始的文本会存储在_source里面,默认情况下其他提取出来的字段都不是独立存储的,是从_source里面提取出来的。当然你也可以独立的存储某个字段,只要设置”store”: true即可,获取独立存储的字段要比从_source中解析快得多,但是也会占用更多的空间,所以要根据实际业务需求来设置。
l analyzer:分词器,这里的ik_max_word即使用ik分词器**
2. 查看类型映射
| 发送请求: |
|---|
| # 请求方法:GET GET /shopping/product/_mapping |
| 响应结果: |
| { “shopping” : { “mappings” : { “product” : { “properties” : { “images” : { “type” : “keyword”, “index” : false }, “price” : { “type” : “float” }, “subtitle” : { “type” : “text”, “analyzer” : “ik_max_word” }, “title” : { “type” : “text”, “analyzer” : “ik_max_word” } } } } } } |
3. 创建索引库同时进行映射配置(常用)
| 发送请求: |
|---|
| # 请求方法:PUT PUT /shopping2 { “settings”: {}, “mappings”: { “product“:{ “properties”: { “title“:{ “type”: “text”, “analyzer”: “ik_max_word” }, “subtitle“:{ “type”: “text”, “analyzer”: “ik_max_word” }, “images“:{ “type”: “keyword”, “index”: false }, “price“:{ “type”: “float”, “index”: true } } } } } |
| 响应结果: |
| { “acknowledged” : true, “shards_acknowledged” : true, “index” : “shopping2” } |
5.4【文档操作】【基本CURD操作】
1. 新建文档
| 发送请求: |
|---|
| # 请求方法:POST POST /shopping/product { “title”:”小米手机”, “images”:”http://www.gulixueyuan.com/xm.jpg“, “price”:3999.00 } |
| 响应结果: |
| { “_index” : “shopping”, “_type” : “product”, “_id” : “indGaHEB1ahbZ0SRrXt3”, “_version” : 1, “result” : “created”, “_shards” : { “total” : 2, “successful” : 1, “failed” : 0 }, “_seq_no” : 0, “_primary_term” : 1 } |
| 响应结果解释: |
| { “_index【索引库】” : “shopping”, “_type【类型】” : “product”, “_id【主键id】” : “indGaHEB1ahbZ0SRrXt3”, “_version【版本】” : 1, “result【操作结果】” : “created”, “_shards【分片】” : { “total【总数】” : 2, “successful【成功】” : 1, “failed【失败】” : 0 }, “_seq_no” : 0, “_primary_term” : 1 } |
可以看到结果显示为:created,是创建成功了。另外,需要注意的是,在响应结果中有个 _id字段,这个就是这条文档数据的唯一标识,以后的增删改查都依赖这个id作为唯一标示。可以看到id的值为:indGaHEB1ahbZ0SRrXt3,这里我们新增时没有指定id,所以是ES帮我们随机生成的id。 |
| 多创建几条数据: POST /shopping/product/2 { “title”:”华为手机”, “images”:”http://www.gulixueyuan.com/hw.jpg“, “price”:4999.00 } POST /shopping/product/3 { “title”:”小米电视”, “images”:”http://www.gulixueyuan.com/xmds.jpg“, “price”:5999.00 } |
2. 查看文档
| 发送请求: |
|---|
| # 请求方法:GET GET /shopping/product/indGaHEB1ahbZ0SRrXt3 ** 多个Id可以使用: |
POST /shopping/product/_search
{
“query”: {
“ids”: {
“values”: [“1”,”2”,”3”]
}
}
} |
| 响应结果: |
| {
“_index” : “shopping”,
“_type” : “product”,
“_id” : “indGaHEB1ahbZ0SRrXt3“,
“_version” : 1,
“_seq_no” : 0,
“_primary_term” : 1,
“found” : true,
“_source” : {
“title” : “小米手机”,
“images” : “http://www.gulixueyuan.com/xm.jpg“,
“price” : 3999.0
}
} |
| 响应结果解释: |
| {
“_index【索引库】” : “shopping”,
“_type【类型】” : “product”,
“_id【主键id】” : “indGaHEB1ahbZ0SRrXt3”,
“_version【版本】” : 1,
“_seq_no” : 0,
“_primary_term” : 1,
“found【查询结果】” : true,
“_source【源文档信息】” : {
“title” : “小米手机”,
“images” : “http://www.gulixueyuan.com/xm.jpg“,
“price” : 3999.0
}
} |
| · _source:源文档信息,所有的数据都在里面。
· _id:这条文档的唯一标示
· found:查询结果,返回true代表查到,false代表没有 |
3. 自定义id新建文档
| 发送请求: |
|---|
| # 请求方法:POST POST /shopping/product/1 { “title”:”小米手机”, “images”:”http://www.gulixueyuan.com/xm.jpg“, “price”:3999.00 } |
| 响应结果: |
| { “_index” : “shopping”, “_type” : “product”, “_id” : “1”, “_version” : 1, “result” : “created”, “_shards” : { “total” : 2, “successful” : 1, “failed” : 0 }, “_seq_no” : 1, “_primary_term” : 1 } |
| · 主键id变为指定的id |
4. 修改文档(覆盖方式)
请求url不变,请求体变化,会将原有数据内容覆盖。
| 发送请求: |
|---|
| # 请求方法:POST POST /shopping/product/1 { “title”:”华为手机”, “images”:”http://www.gulixueyuan.com/hw.jpg“, “price”:4999.00 } |
| 响应结果: |
| { “_index” : “shopping”, “_type” : “product”, “_id” : “1”, “_version” :** 2,** “result” : “updated”, “_shards” : { “total” : 2, “successful” : 1, “failed” : 0 }, “_seq_no” : 2, “_primary_term” : 1 } |
| 可以看到result结果是:updated,使用GET /shopping/product/1查询,发现数据被更新。如果有一个字段没有写的话,就会恢复为默认值 |
5. 根据id修改某一个字段
| 发送请求: |
|---|
| # 请求方法:POST POST /shopping/product/1/_update { “doc”: { “price”:3000.00 } } |
| 响应结果: |
| { “_index” : “shopping”, “_type” : “product”, “_id” : “1”, “_version” : 2, “result” : “updated”, “_shards” : { “total” : 2, “successful” : 1, “failed” : 0 }, “_seq_no” : 8, “_primary_term” : 1 } |
| 可以看到result结果是:updated,使用GET /shopping/product/1查询,发现数据被更新。 |
6. 删除一条文档
删除一个文档不会立即从磁盘上移除,它只是被标记成已删除(逻辑删除)。
Elasticsearch会在段合并时(磁盘碎片整理)进行删除内容的清理。
| 发送请求: |
|---|
| # 请求方法:DELETE DELETE /shopping/product/1 |
| 响应结果: |
| { “_index” : “shopping”, “_type” : “product”, “_id” : “1”, “_version” : 3, “result” : “deleted”, “_shards” : { “total” : 2, “successful” : 1, “failed” : 0 }, “_seq_no” : 3, “_primary_term” : 1 } |
| 可以看到result结果是:deleted,数据被删除。如果删除不存在的文档,result:not_found |
| 例如:DELETE /shopping/product/11主键不存在 |
| { “_index” : “shopping”, “_type” : “product”, “_id” : “11”, “_version” : 1, “result” : “not_found”, “_shards” : { “total” : 2, “successful” : 1, “failed” : 0 }, “_seq_no” : 0, “_primary_term” : 1 } |
7. 根据条件删除文档
| 发送请求: |
|---|
| # 请求方法:DELETE POST /shopping/_delete_by_query { “query”:{ “match”:{ “title”:”手机” } } } |
| 响应结果: |
| { “took” : 33, “timed_out” : false, “total” : 2, “deleted” : 2, “batches” : 1, “version_conflicts” : 0, “noops” : 0, “retries” : { “bulk” : 0, “search” : 0 }, “throttled_millis” : 0, “requests_per_second” : -1.0, “throttled_until_millis” : 0, “failures” : [ ] } |
| 响应结果解释: |
| { “took【耗时】” : 33, “timed_out【是否超时】” : false, “total【总数】” : 2, “deleted【删除总数】” : 2, “batches” : 1, “version_conflicts” : 0, “noops” : 0, “retries” : { “bulk” : 0, “search” : 0 }, “throttled_millis” : 0, “requests_per_second” : -1.0, “throttled_until_millis” : 0, “failures” : [ ] } |
5.5【请求体查询】【基本查询】
1. 请求体查询
Elasticsearch基于JSON提供完整的查询DSL来定义查询。
DSL(Domain Specific Language):领域特定语言
2. 基础数据
| POST /shopping/product/1 { “title”:”小米手机”, “images”:”http://www.gulixueyuan.com/xm.jpg“, “price”:3999.00 } POST /shopping/product/2 { “title”:”华为手机”, “images”:”http://www.gulixueyuan.com/hw.jpg“, “price”:4999.00 } POST /shopping/product/3 { “title”:”小米电视”, “images”:”http://www.gulixueyuan.com/xmds.jpg“, “price”:5999.00 } |
|---|
3. 基本查询
1) 查询所有(match_all)
默认查询10条
| 发送请求: |
|---|
| # 请求方法:GET #请求地址:http://127.0.0.1:9200/索引库名/_search GET /shopping/_search { “query”: { “match_all”: {} } } |
| 请求解释: |
| GET /{索引库}/_search { “query”:{ “查询类型”:{ “查询条件”:”查询条件值” } } } “query”:这里的query代表一个查询对象,里面可以有不同的查询属性 “查询类型”:例如:match_all(代表查询所有), match,term , range 等等 “查询条件”:查询条件会根据类型的不同,写法也有差异 |
| 响应结果: |
| { “took” : 1, “timed_out” : false, “_shards” : { “total” : 5, “successful” : 5, “skipped” : 0, “failed” : 0 }, “hits” : { “total” : 3, “max_score” : 1.0, “hits” : [ { “_index” : “shopping”, “_type” : “product”, “_id” : “2”, “_score” : 1.0, “_source” : { “title” : “华为手机”, “images” : “http://www.gulixueyuan.com/hw.jpg“, “price” : 4999.0 } }, { “_index” : “shopping”, “_type” : “product”, “_id” : “1”, “_score” : 1.0, “_source” : { “title” : “小米手机”, “images” : “http://www.gulixueyuan.com/xm.jpg“, “price” : 3999.0 } }, { “_index” : “shopping”, “_type” : “product”, “_id” : “3”, “_score” : 1.0, “_source” : { “title” : “小米电视”, “images” : “http://www.gulixueyuan.com/xmds.jpg“, “price” : 5999.0 } } ] } } |
| 响应结果解释: |
| { “took【查询花费时间,单位毫秒】” : 1, “timed_out【是否超时】” : false, “_shards【分片信息】” : { “total【总数】” : 5, “successful【成功】” : 5, “skipped【忽略】” : 0, “failed【失败】” : 0 }, “hits【搜索命中结果】” : { “total【命中总数】” : 3, “max_score【所有查询结果中,文档的最高得分】” : 1.0, “hits【命中结果集合】” : [ { “_index” : “shopping”, “_type” : “product”, “_id” : “2”, “_score” : 1.0, “_source” : { “title” : “华为手机”, “images” : “http://www.gulixueyuan.com/hw.jpg“, “price” : 4999.0 } }, 。。。 } ] } } |
2) 匹配查询(match)
match类型查询,会把查询条件进行分词,然后进行查询,多个词条之间是or的关系
match查询底层就是多个term查询,是将多个trem查询结果给你拼装在一起
属于高层查询,根据你查询的字段类型不一样,采用不同的查询方式
- 查询是日期或者数值的话,他会基于你的字符串查询内容转换为日期或者数值对待
- 如果查询的是一个不能分词的内容(keyword) ,match查询不会对你的指定查询关键字进行分词
- 如果查询的内容是一个可以被分词的内容(text),match会将你指定的查询内容根据一定的方式去分词,去分词库中匹配指定的内容
| 发送请求: |
| —- |
| # 请求方法:GET
GET /shopping/_search
{
“query”: {
“match”: {
“title”: “小米手机”
}
}
}
精确匹配
GET /shopping/_search
{
“query”: {
“match”: {
“title.keyword”: “小米手机”
}
}
} |
| 响应结果: |
| {
“took” : 2,
“timed_out” : false,
“_shards” : {
“total” : 5,
“successful” : 5,
“skipped” : 0,
“failed” : 0
},
“hits” : {
“total” : 3,
“max_score” : 0.5753642,
“hits” : [
{
“_index” : “shopping”,
“_type” : “product”,
“_id” : “1”,
“_score” : 0.5753642,
“_source” : {
“title” : “小米手机”,
“images” : “http://www.gulixueyuan.com/xm.jpg“,
“price” : 3999.0
}
},
{
“_index” : “shopping”,
“_type” : “product”,
“_id” : “2”,
“_score” : 0.2876821,
“_source” : {
“title” : “华为手机”,
“images” : “http://www.gulixueyuan.com/hw.jpg“,
“price” : 4999.0
}
},
{
“_index” : “shopping”,
“_type” : “product”,
“_id” : “3”,
“_score” : 0.2876821,
“_source” : {
“title” : “小米电视”,
“images” : “http://www.gulixueyuan.com/xmds.jpg“,
“price” : 5999.0
}
}
]
}
} |
| 在上面的案例中,不仅会查询到电视,而且与小米相关的都会查询到。
某些情况下,我们需要更精确查找,我们希望这个关系变成and,可以这样做: |
| 发送请求:
本例中,只有同时包含小米和手机的词条才会被搜索到。其中and 也可以使用or |
| GET /shopping/_search
{
“query”: {
“match”: {
“title”: {
“query”: “小米手机”,
“operator”: “and”
}
}
}
} |
| 响应结果: |
| {
“took” : 11,
“timed_out” : false,
“_shards” : {
“total” : 5,
“successful” : 5,
“skipped” : 0,
“failed” : 0
},
“hits” : {
“total” : 1,
“max_score” : 0.5753642,
“hits” : [
{
“_index” : “shopping”,
“_type” : “product”,
“_id” : “1”,
“_score” : 0.5753642,
“_source” : {
“title” : “小米手机”,
“images” : “http://www.gulixueyuan.com/xm.jpg“,
“price” : 3999.0
}
}
]
}
} |
3) 多字段匹配查询(multi_match)
multi_match与match类似,不同的是它可以在多个字段中查询。
| 发送请求: |
|---|
| # 请求方法:GET #fields属性:设置查询的多个字段名称 GET /shopping/_search { “query”: { “multi_match“: { “query”: “小米”, “fields”: [“title”,”subtitle”] } } } |
| 响应结果: |
| { “took” : 1, “timed_out” : false, “_shards” : { “total” : 5, “successful” : 5, “skipped” : 0, “failed” : 0 }, “hits” : { “total” : 2, “max_score” : 0.2876821, “hits” : [ { “_index” : “shopping”, “_type” : “product”, “_id” : “1”, “_score” : 0.2876821, “_source” : { “title” : “小米手机”, “images” : “http://www.gulixueyuan.com/xm.jpg“, “price” : 3999.0 } }, { “_index” : “shopping”, “_type” : “product”, “_id” : “3”, “_score” : 0.2876821, “_source” : { “title” : “小米电视”, “images” : “http://www.gulixueyuan.com/xmds.jpg“, “price” : 5999.0 } } ] } } |
4) 关键词精确查询(term)
term查询,精确的关键词匹配查询,不对查询条件进行分词。
如果你搜索小米手机,此时是没有结果的,因为ik将小米手机分为(小米,米,手机),而你的搜索为小米手机,匹配不到所以没有数据
| 发送请求: |
|---|
| # 请求方法:GET GET /shopping/_search { “query”: { “term”: { “title”: { “value”: “小米” } } } } |
| 响应结果: |
| { “took” : 0, “timed_out” : false, “_shards” : { “total” : 5, “successful” : 5, “skipped” : 0, “failed” : 0 }, “hits” : { “total” : 2, “max_score” : 0.2876821, “hits” : [ { “_index” : “shopping”, “_type” : “product”, “_id” : “1”, “_score” : 0.2876821, “_source” : { “title” : “小米手机”, “images” : “http://www.gulixueyuan.com/xm.jpg“, “price” : 3999.0 } }, { “_index” : “shopping”, “_type” : “product”, “_id” : “3”, “_score” : 0.2876821, “_source” : { “title” : “小米电视”, “images” : “http://www.gulixueyuan.com/xmds.jpg“, “price” : 5999.0 } } ] } } |
5) 多关键词精确查询(terms)
terms 查询和 term 查询一样,但它允许你指定多值进行匹配。
如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件,类似于mysql的in
| 发送请求: |
|---|
| # 请求方法:GET GET /shopping/_search { “query”: { “terms“: { “price”: [3999,5999] } } } |
| 响应结果: |
| { “took” : 0, “timed_out” : false, “_shards” : { “total” : 5, “successful” : 5, “skipped” : 0, “failed” : 0 }, “hits” : { “total” : 2, “max_score” : 1.0, “hits” : [ { “_index” : “shopping”, “_type” : “product”, “_id” : “1”, “_score” : 1.0, “_source” : { “title” : “小米手机”, “images” : “http://www.gulixueyuan.com/xm.jpg“, “price” : 3999.0 } }, { “_index” : “shopping”, “_type” : “product”, “_id” : “3”, “_score” : 1.0, “_source” : { “title” : “小米电视”, “images” : “http://www.gulixueyuan.com/xmds.jpg“, “price” : 5999.0 } } ] } } |
5.6【请求体查询】【结果过滤】
1. 指定查询字段
默认情况下,ElasticSearch在搜索的结果中,会把文档中保存在_source的所有字段都返回。
如果我们只想获取其中的部分字段,我们可以添加_source的过滤
| 发送请求: |
|---|
| # 请求方法:GET GET /shopping/_search { “_source”: [“title”,”price”], “query”: { “terms”: { “price”: [3999] } } } |
| 响应结果: |
| { “took” : 0, “timed_out” : false, “_shards” : { “total” : 5, “successful” : 5, “skipped” : 0, “failed” : 0 }, “hits” : { “total” : 1, “max_score” : 1.0, “hits” : [ { “_index” : “shopping”, “_type” : “product”, “_id” : “1”, “_score” : 1.0, “_source” : { “price” : 3999.0, “title” : “小米手机” } } ] } } |
2. 过滤指定字段:includes和excludes
我们也可以通过:
includes:来指定想要显示的字段
excludes:来指定不想要显示的字段
二者都是可选的。
| 发送请求: |
|---|
| # 请求方法:GET GET /shopping/_search { “_source”: { “includes”: [“title”,”price”] }, “query”: { “terms”: { “price”: [3999] } } } GET /shopping/_search { “_source”: { “excludes”: [“images”] }, “query”: { “terms”: { “price”: [3999] } } } |
| 响应结果: |
| { “took” : 0, “timed_out” : false, “_shards” : { “total” : 5, “successful” : 5, “skipped” : 0, “failed” : 0 }, “hits” : { “total” : 1, “max_score” : 1.0, “hits” : [ { “_index” : “shopping”, “_type” : “product”, “_id” : “1”, “_score” : 1.0, “_source” : { “price” : 3999.0, “title” : “小米手机” } } ] } } |
5.7【请求体查询】【高级查询】
1. 布尔组合(bool)
bool把各种其它查询通过must(必须 )、must_not(必须不 )、should(应该)的方式进行组合
| 发送请求: |
|---|
| # 请求方法:GET GET /shopping/_search { “query”: { “bool“: { “must“: [ { “match”: { “title”: “小米” } } ], “must_not“: [ { “match”: { “title”: “电视” } } ], “should“: [ { “match”: { “title”: “手机” } } ], “filter“: { “match”: { “title”: “华为” } } } } } } |
| 响应结果: |
| { “took” : 2, “timed_out” : false, “_shards” : { “total” : 5, “successful” : 5, “skipped” : 0, “failed” : 0 }, “hits” : { “total” : 1, “max_score” : 0.5753642, “hits” : [ { “_index” : “shopping”, “_type” : “product”, “_id” : “1”, “_score” : 0.5753642, “_source” : { “title” : “小米手机”, “images” : “http://www.gulixueyuan.com/xm.jpg“, “price” : 3999.0 } } ] } } |
2. 范围查询(range)
range 查询找出那些落在指定区间内的数字或者时间。range查询允许以下字符:
| 操作符 | 说明 |
|---|---|
| gt == (greater than) | 大于> |
| gte == (greater than equal) | 大于等于>= |
| lt == (less than) | 小于< |
| lte == (less than equal) | 小于等于<= |
| 发送请求: | |
| # 请求方法:GET GET /shopping/_search { “query”: { “range“: { “price”: { “gte”: 2500, “lte”: 4000 } } } } |
|
| 响应结果: | |
| { “took” : 0, “timed_out” : false, “_shards” : { “total” : 5, “successful” : 5, “skipped” : 0, “failed” : 0 }, “hits” : { “total” : 1, “max_score” : 1.0, “hits” : [ { “_index” : “shopping”, “_type” : “product”, “_id” : “1”, “_score” : 1.0, “_source” : { “title” : “小米手机”, “images” : “http://www.gulixueyuan.com/xm.jpg“, “price” : 3999.0 } } ] } } |
3. 模糊查询(fuzzy)
返回包含与搜索字词相似的字词的文档。
编辑距离是将一个术语转换为另一个术语所需的一个字符更改的次数。这些更改可以包括:
更改字符(box → fox)
删除字符(black → lack)
插入字符(sic → sick)
转置两个相邻字符(act → cat)
为了找到相似的术语,fuzzy查询会在指定的编辑距离内创建一组搜索词的所有可能的变体或扩展。然后查询返回每个扩展的完全匹配。
通过fuzziness修改编辑距离。一般使用默认值AUTO,根据术语的长度生成编辑距离。
0..2
必须完全匹配
3..5
允许一次编辑
>5
允许进行两次编辑
| POST /shopping/product/4 { “title”:”apple手机”, “images”:”http://www.gulixueyuan.com/apple.jpg“, “price”:5999.00 } POST /shopping/product/5 { “title”:”apple”, “images”:”http://www.gulixueyuan.com/apple.jpg“, “price”:4999.00 } |
|---|
| 发送请求: |
| # 请求方法:GET GET /shopping/_search { “query”: { “fuzzy”: { “title”: { “value”: “ccple” } } } } GET /shopping/_search { “query”: { “fuzzy”: { “title”: { “value”: “ccple”, “fuzziness”: 2, “prefix_lenth”: 2 #指定前面几个字符不允许出现错误 } } } } |
| 响应结果: |
| { “took” : 0, “timed_out” : false, “_shards” : { “total” : 5, “successful” : 5, “skipped” : 0, “failed” : 0 }, “hits” : { “total” : 0, “max_score” : null, “hits” : [ ] } } ————————————————— { “took” : 1, “timed_out” : false, “_shards” : { “total” : 5, “successful” : 5, “skipped” : 0, “failed” : 0 }, “hits” : { “total” : 2, “max_score” : 0.41588834, “hits” : [ { “_index” : “shopping”, “_type” : “product”, “_id” : “4”, “_score” : 0.41588834, “_source” : { “title” : “apple手机”, “images” : “http://www.gulixueyuan.com/apple.jpg“, “price” : 5999.0 } }, { “_index” : “shopping”, “_type” : “product”, “_id” : “5”, “_score” : 0.17260925, “_source” : { “title” : “apple”, “images” : “http://www.gulixueyuan.com/apple.jpg“, “price” : 4999.0 } } ] } } |
4. 前缀查询(prefix)
前缀查询根据关键字去指定一个field的前缀,查询指定的文档
{"query": {"prefix": {"title": {"value": "小米"}}}}
5. 通配符查询(wildcard)
通配查询,和MySQL中的like是一个套路,可以在查询时,在字符串指定通配符*和占位符?
{"query": {"wildcard": {"title": {"value": "手机*"}}}}
6. 正则查询(regexp)
正则查询你可以通过你编写的正则表达式去表示内容
{"query":{"regexp": {"price": "正则表达式"}}}
prefix,fuzzy,wildcard,regexp查询效率相对比较低
7. boosting查询
boosting查询可以帮助我们去影响查询后面的score
- positive : 只有匹配上positive的查询内容,才会放到返回的结果集
- negative : 如果匹配上和positive并且也匹配上了negative,就可以降低这样的文档score
- negative_boost: 指定系数,必须小于1.0
关于查询时,分数时如何计算 :
- 搜索的关键字在文档中出现的频次越高,分数越高
- 指定的文档内容越短,分数也就越高
- 我们在搜索时,指定的关键字也会被分词,这个被分词的内容,被分词库匹配的个数越多也就越高
POST /shopping01/_search{"query": {"boosting": {# 匹配你的结果集"positive": {"match": {"title": "手机"}},# 在 匹配了结果集后又匹配了negative,就把原来的系数去乘以negative_boost"negative": {"match": {"title": "华为"}},"negative_boost": 0.5}}}
8. filter查询
query : 根据你的查询条件,去计算文档的匹配得到一个分数,并且根据分数进行排序,不会做缓存
filter : 根据你的查询条件去查询文档,不去计算分数,而且filter会对经常被过滤的数据进行缓存
POST /shopping01/_search{"query": {"bool": {"filter":[{"term":{"title": "华为"}},{"term":{"price": 4999}}]}}}
查询结果 :
{"took" : 0,"timed_out" : false,"_shards" : {"total" : 5,"successful" : 5,"skipped" : 0,"failed" : 0},"hits" : {"total" : 1,"max_score" : 0.0,"hits" : [{"_index" : "shopping01","_type" : "_doc","_id" : "0xrnOXcB9XTB6Ta8HWB9","_score" : 0.0,"_source" : {"title" : "华为手机","images" : "http://www.gulixueyuan.com/hw.jpg","price" : 4999.0,"subtitle" : "小米"}}]}}
5.8【请求体查询】【查询排序】
1. 单字段排序
sort 可以让我们按照不同的字段进行排序,并且通过order指定排序的方式。desc降序,asc升序。
| 发送请求: |
|---|
| # 请求方法:GET GET /shopping/_search { “query”: { “match_all”: {} }, “sort”: [ { “price”: { “order”: “desc” } } ] } |
| 响应结果: |
| { “took” : 4, “timed_out” : false, “_shards” : { “total” : 5, “successful” : 5, “skipped” : 0, “failed” : 0 }, “hits” : { “total” : 5, “max_score” : null, “hits” : [ { “_index” : “shopping”, “_type” : “product”, “_id” : “4”, “_score” : null, “_source” : { “title” : “apple手机”, “images” : “http://www.gulixueyuan.com/apple.jpg“, “price” : 5999.0 }, “sort” : [ 5999.0 ] }, { “_index” : “shopping”, “_type” : “product”, “_id” : “3”, “_score” : null, “_source” : { “title” : “小米电视”, “images” : “http://www.gulixueyuan.com/xmds.jpg“, “price” : 5999.0 }, “sort” : [ 5999.0 ] }, { “_index” : “shopping”, “_type” : “product”, “_id” : “5”, “_score” : null, “_source” : { “title” : “apple”, “images” : “http://www.gulixueyuan.com/apple.jpg“, “price” : 4999.0 }, “sort” : [ 4999.0 ] }, { “_index” : “shopping”, “_type” : “product”, “_id” : “2”, “_score” : null, “_source” : { “title” : “华为手机”, “images” : “http://www.gulixueyuan.com/hw.jpg“, “price” : 4999.0 }, “sort” : [ 4999.0 ] }, { “_index” : “shopping”, “_type” : “product”, “_id” : “1”, “_score” : null, “_source” : { “title” : “小米手机”, “images” : “http://www.gulixueyuan.com/xm.jpg“, “price” : 3999.0 }, “sort” : [ 3999.0 ] } ] } } |
2. 多字段排序
假定我们想要结合使用 price和 _score(得分) 进行查询,并且匹配的结果首先按照价格排序,然后按照相关性得分排序:
| 发送请求: |
|---|
| # 请求方法:GET GET /shopping/_search { “query”: { “match_all”: {} }, “sort”: [ { “price”: { “order”: “desc” } }, { “_score”:{ “order”: “desc” } } ] } |
| 响应结果: |
| { “took” : 0, “timed_out” : false, “_shards” : { “total” : 5, “successful” : 5, “skipped” : 0, “failed” : 0 }, “hits” : { “total” : 5, “max_score” : null, “hits” : [ { “_index” : “shopping”, “_type” : “product”, “_id” : “4”, “_score” : 1.0, “_source” : { “title” : “apple手机”, “images” : “http://www.gulixueyuan.com/apple.jpg“, “price” : 5999.0 }, “sort” : [ 5999.0, 1.0 ] }, { “_index” : “shopping”, “_type” : “product”, “_id” : “3”, “_score” : 1.0, “_source” : { “title” : “小米电视”, “images” : “http://www.gulixueyuan.com/xmds.jpg“, “price” : 5999.0 }, “sort” : [ 5999.0, 1.0 ] }, { “_index” : “shopping”, “_type” : “product”, “_id” : “5”, “_score” : 1.0, “_source” : { “title” : “apple”, “images” : “http://www.gulixueyuan.com/apple.jpg“, “price” : 4999.0 }, “sort” : [ 4999.0, 1.0 ] }, { “_index” : “shopping”, “_type” : “product”, “_id” : “2”, “_score” : 1.0, “_source” : { “title” : “华为手机”, “images” : “http://www.gulixueyuan.com/hw.jpg“, “price” : 4999.0 }, “sort” : [ 4999.0, 1.0 ] }, { “_index” : “shopping”, “_type” : “product”, “_id” : “1”, “_score” : 1.0, “_source” : { “title” : “小米手机”, “images” : “http://www.gulixueyuan.com/xm.jpg“, “price” : 3999.0 }, “sort” : [ 3999.0, 1.0 ] } ] } } |
5.9【请求体查询】【高亮查询】
在进行关键字搜索时,搜索出的内容中的关键字会显示不同的颜色,称之为高亮。
l 在百度搜索”京东”
l 在京东网站搜索“小米”
l 高亮显示的html分析
通过开发者工具查看高亮数据的html代码实现:
l 高亮查询请求
ElasticSearch可以对查询内容中的关键字部分,进行标签和样式(高亮)的设置。
在使用match查询的同时,加上一个highlight属性:
pre_tags:前置标签
post_tags:后置标签
fields:需要高亮的字段
title:这里声明title字段需要高亮,后面可以为这个字段设置特有配置,也可以空
fragment_size:指定高亮数据展示多少个字符回来
| 发送请求: |
|---|
| # 请求方法:GET GET /shopping/_search { “query”: { “match”: { “title”: “华为” } }, “highlight”: { “pre_tags”: ““, “post_tags”: ““, “fields”: { “title”: {} } } } |
| 响应结果: |
| { “took” : 1, “timed_out” : false, “_shards” : { “total” : 5, “successful” : 5, “skipped” : 0, “failed” : 0 }, “hits” : { “total” : 1, “max_score” : 0.6931472, “hits” : [ { “_index” : “shopping”, “_type” : “product”, “_id” : “2”, “_score” : 0.6931472, “_source” : { “title” : “华为手机”, “images” : “http://www.gulixueyuan.com/hw.jpg“, “price” : 4999.0 }, “highlight” : { “title” : [ “华为手机” ] } } ] } } |
5.10【请求体查询】【分页查询】
l from:当前页的起始索引,默认从0开始。 from = (pageNum - 1) * size
l size:每页显示多少条
| 发送请求: |
|---|
| # 请求方法:GET GET /shopping/_search { “query”: { “match_all”: {} }, “sort”: [ { “price”: { “order”: “desc” } }, { “_score”:{ “order”: “desc” } } ], “from”: 0, “size”: 2 } |
| 响应结果: |
| { “took” : 0, “timed_out” : false, “_shards” : { “total” : 5, “successful” : 5, “skipped” : 0, “failed” : 0 }, “hits” : { “total” : 5, “max_score” : null, “hits” : [ { “_index” : “shopping”, “_type” : “product”, “_id” : “4”, “_score” : 1.0, “_source” : { “title” : “apple手机”, “images” : “http://www.gulixueyuan.com/apple.jpg“, “price” : 5999.0 }, “sort” : [ 5999.0, 1.0 ] }, { “_index” : “shopping”, “_type” : “product”, “_id” : “3”, “_score” : 1.0, “_source” : { “title” : “小米电视”, “images” : “http://www.gulixueyuan.com/xmds.jpg“, “price” : 5999.0 }, “sort” : [ 5999.0, 1.0 ] } ] } } |
from + size是有限制的,from和size二者之和不能超过1w
1. ES查询数据的方式
- 先将用户指定的关键字进行分词
- 将词汇去分词库中进行检索,得到多个文档的Id
- 去各个分片拿去指定的数据
- 将数据根据score进行排序
- 根据from的值,将查询的结构舍弃一部份
- 返回结构
2. 深分页 (Scroll)
- 先将用户指定的关键字进行分词
- 将词汇去分词库中进行检索,得到多个文档的Id
- 将文档Id存放在一个Es上下文中
- 将数据根据你指定的size个数去ES中检索指定的数据,拿完数据的文档Id,会从上下文去移除
- 如果需要下一页数据,直接去ES上下文中,找后续内容,不会再去查询
- 循环第四步第五步
注意 : 不适合到实时查询 :
#1m表示查询数据返回第一页数据,放到上下文1分钟,没有使用就将他删除GET /shopping01/_search?scroll=1m{"query": {"match_all": {}},"size": 2,"sort": [{"price": {"order": "desc"}}]}
结果 :
{"_scroll_id" : "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAEf2Fjc1TjctdHlVU0hlTlBtTVdRampMLXcAAAAAAABH9RY3NU43LXR5VVNIZU5QbU1XUWpqTC13AAAAAAAAR_cWNzVONy10eVVTSGVOUG1NV1FqakwtdwAAAAAAAEf4Fjc1TjctdHlVU0hlTlBtTVdRampMLXcAAAAAAABH-RY3NU43LXR5VVNIZU5QbU1XUWpqTC13","took" : 0,"timed_out" : false,"_shards" : {"total" : 5,"successful" : 5,"skipped" : 0,"failed" : 0},"hits" : {"total" : 6,"max_score" : null,"hits" : [{"_index" : "shopping01","_type" : "_doc","_id" : "1BrnOXcB9XTB6Ta8HWB9","_score" : null,"_source" : {"title" : "apple手机","images" : "http://www.gulixueyuan.com/appletl.jpg","price" : 5999.0},"sort" : [5999.0]},{"_index" : "shopping01","_type" : "_doc","_id" : "0xrnOXcB9XTB6Ta8HWB9","_score" : null,"_source" : {"title" : "华为手机","images" : "http://www.gulixueyuan.com/hw.jpg","price" : 4999.0,"subtitle" : "小米"},"sort" : [4999.0]}]}}
根据scroll查询下一页数据
GET /_search/scroll{"scroll_id":"DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAEj_Fjc1TjctdHlVU0hlTlBtTVdRampMLXcAAAAAAABJARY3NU43LXR5VVNIZU5QbU1XUWpqTC13AAAAAAAASQIWNzVONy10eVVTSGVOUG1NV1FqakwtdwAAAAAAAEkAFjc1TjctdHlVU0hlTlBtTVdRampMLXcAAAAAAABI_hY3NU43LXR5VVNIZU5QbU1XUWpqTC13","scroll": "1m"}
删除scroll在Es上下文中的数据
DELETE /_search/scroll/DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAEj_Fjc1TjctdHlVU0hlTlBtTVdRampMLXcAAAAAAABJARY3NU43LXR5VVNIZU5QbU1XUWpqTC13AAAAAAAASQIWNzVONy10eVVTSGVOUG1NV1FqakwtdwAAAAAAAEkAFjc1TjctdHlVU0hlTlBtTVdRampMLXcAAAAAAABI_hY3NU43LXR5VVNIZU5QbU1XUWpqTC13
5.11聚合查询
ES的聚合查询和Mysql的聚合查询类型,Es的聚合查询相比MySQL更强大的多,Es统计数据的方式多种多样
1. 去重计数查询
去重计数,即cardinality,第一步先将返回的文档中的一个指定的field进行去重,统计多少条
GET /shopping01/_search{"aggs": {"agg": {"cardinality": {"field": "title"}}}}
2. 范围统计
统计一定范围内出现的文档个数,比如 : 针对某一个field的值在0-100,100-200之间文档出现的个数
范围统计可以针对普通的数值,,针对时间的类型,针对ip类型都可以做相应的统计
range ; data_range ; ip_range
数值 :
GET /shopping01/_search{"aggs": {"agg": {"range": {"field": "price","ranges": [{#查询price小于3000"to": 3000},{#查询大于等于3000,小于4000"from": 3000,"to": 4000},{#查询大于等于4000"from": 4000#from有包含当前值}]}}}}
时间 :
GET /shopping01/_search{"aggs": {"agg": {"data_range": {"field": "createDate","format": "yyyy","ranges": [{"to": 2000},{"from": 4000}]}}}}
ip范围
GET /shopping01/_search{"aggs": {"agg": {"ip_range": {"field": "ipAddr","ranges": [{"to": "192.168.11.0},{"from": "192.168.11.200}]}}}}
3. 统计聚合查询
它可以帮助你查询指定field的最大值,最小值,平均值,平方和
GET /shopping01/_search{"aggs": {"agg": {"extended_stats": {"field": "price"}}}}
结果 :
................ 省略"aggregations" : {"agg" : {"count" : 6,"min" : 1999.0,"max" : 5999.0,"avg" : 3832.3333333333335,"sum" : 22994.0,"sum_of_squares" : 9.8954006E7,"variance" : 1805555.5555555548,"std_deviation" : 1343.7096247164247,"std_deviation_bounds" : {"upper" : 6519.752582766183,"lower" : 1144.914083900484}}}
5.12 地图经纬度搜索
Es提供了一个数据类型geo_point,这个类型就是用来存储经纬度的
地图检索方式 :
- geo_distance : 以一个点为中心直线花园距离检索
- geo_bounding_box : 以两个点确定一个矩形,获取在矩形内的全部数据
- geo_polygon : 以多个点确定多边形,获取多边形内的全部数据
GET /map/_search{"query" {"geo_distance": {"location": { #确定一个点"lon": 116.433733,"lat": 39.908404}"distance": 2000 #确定半径"distance_type": "arc" # 指定形状为圆形}}}GET /map/_search{"query" {"geo_distance": {"location": {"top_left": { #左上坐标点"lon": 116.433733,"lat": 39.908404},"bottom_right": { # 右下坐标点"lon": 116.433733,"lat": 39.908737}}}}}GET /map/_search{"query" {"geo_polygon": {"location": {"points": [ #指定多个点确定一个多边形{"lon": 116.433733,"lat": 39.908404},{"lon": 116.433733,"lat": 39.901231}}}}}}


