【ElasticSearch 学习笔记】索引操作、文档操作

学习视频:【尚硅谷】ElasticSearch 入门到精通(基于 ELK 技术栈 elasticsearch 7.8.x 版本)

学习大纲:

  • 第 1 章 Elasticsearch 概述
  • 第 2 章 Elasticsearch 入门
  • 第 3 章 Elasticsearch 环境
  • 第 4 章 Elasticsearch 进阶
  • 第 5 章 Elasticsearch 集成
  • 第 6 章 Elasticsearch 优化
  • 第 7 章 Elasticsearch 面试题

第 1 章 ElasticSearch 概述

结构化数据:

非结构化数据:

半结构化数据:

技术选型

Elasticsearch 是什么

The Elastic Stack 包括 Elasticsearch、 Kibana、 Beats 和 Logstash(也称为 ELK Stack)。能够安全可靠地获取任何来源、任何格式的数据,然后实时地对数据进行搜索、分析和可视化。

Elaticsearch 简称为 ES,它是一个开源的高扩展的分布式全文搜索引擎, 是整个 ElasticStack 技术栈的核心。

扫描二维码关注公众号,回复: 13776452 查看本文章

它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理 PB 级别的数据。

全文搜索引擎

Google、百度类 的网站搜索,都是根据网页中的关键字生成索引,我们在搜索的时候输入关键字,它们会将该关键字即索引匹配到的所有网页返回;还有常见的项目中应用日志的搜索等等。对于这些非结构化的数据文本,关系型数据库搜索不是能很好的支持。

一般传统数据库,全文检索都实现的很鸡肋,因为一般也没人用数据库存文本字段。进行全文检索需要扫描整个表,如果数据量大的话即使对 SQL 的语法优化,也收效甚微。建立了索引,但是维护起来也很麻烦,对于 insert 和 update 操作都会重新构建索引。

基于以上原因可以分析得出,在一些生产环境中,使用常规的搜索方式,性能是非常差的:

  • 搜索的数据对象是大量的非结构化的文本数据。
  • 文件记录量达到数十万或数百万个甚至更多。
  • 支持大量基于交互式文本的查询。
  • 需求非常灵活的全文搜索查询。
  • 对高度相关的搜索结果的有特殊需求,但是没有可用的关系数据库可以满足。
  • 对不同记录类型、非文本数据操作或安全事务处理的需求相对较少的情况。为了解决结构化数据搜索和非结化数据搜索性能问题,我们就需要专业,健壮,强大的全文搜索引擎 。

这里说到的全文搜索引擎指的是目前广泛应用的主流搜索引擎。它的工作原理是计算机索引程序通过扫描文章中的每一个词,对每一个词建立一个索引,指明该词在文章中出现的次数和位置,当用户查询时,检索程序就根据事先建立的索引进行查找,并将查找的结果反馈给用户的检索方式。这个过程类似于通过字典中的检索字表查字的过程。

Elasticsearch 应用案例

  • GitHub:2013 年初,抛弃了 Solr,采取 Elasticsearch 来做 PB 级的搜索。 “GitHub 使用Elasticsearch 搜索 20TB 的数据,包括 13 亿文件和 1300 亿行代码”。
  • 维基百科:启动以 Elasticsearch 为基础的核心搜索架构
  • 百度:目前广泛使用 Elasticsearch 作为文本数据分析,采集百度所有服务器上的各类指标数据及用户自定义数据,通过对各种数据进行多维分析展示,辅助定位分析实例异常或业务层面异常。目前覆盖百度内部 20 多个业务线(包括云分析、网盟、预测、文库、直达号、钱包、 风控等),单集群最大 100 台机器, 200 个 ES 节点,每天导入 30TB+ 数据。
  • 新浪:使用 Elasticsearch 分析处理 32 亿条实时日志。
  • 阿里:使用 Elasticsearch 构建日志采集和分析体系。
  • Stack Overflow:解决 Bug 问题的网站,全英文,编程人员交流的网站。

第 2 章 ElasticSearch 入门

环境准备

Elastic 官网:开源搜索:Elasticsearch、ELK Stack 和 Kibana 的开发者 | Elastic

ElasticSearch 镜像下载地址:https://mirrors.huaweicloud.com/elasticsearch/

Windows 版的 Elasticsearch 压缩包,解压即安装完毕,解压后的 Elasticsearch 的目录结构如下 :

目录 含义
bin 可执行脚本目录
config 配置目录
jdk 内置 JDK 目录
lib 类库
logs 日志目录
modules 模块目录
plugins 插件目录

解压后,进入 bin 文件目录,点击 elasticsearch.bat 文件启动 ES 服务 。

9300 端口为 Elasticsearch 集群间组件的通信端口, 9200 端口为浏览器访问的 http 协议 RESTful 端口。

打开浏览器,输入地址: http://localhost:9200,测试返回结果,返回结果如下:

以下是 Mac 电脑 的返回结果

{
    
    
    "name": "air.local",
    "cluster_name": "elasticsearch",
    "cluster_uuid": "Zf7_bFjkSC6COYPBgeybTw",
    "version": {
    
    
        "number": "7.8.0",
        "build_flavor": "default",
        "build_type": "tar",
        "build_hash": "757314695644ea9a1dc2fecd26d1a43856725e65",
        "build_date": "2020-06-14T19:35:50.234439Z",
        "build_snapshot": false,
        "lucene_version": "8.5.1",
        "minimum_wire_compatibility_version": "6.8.0",
        "minimum_index_compatibility_version": "6.0.0-beta1"
    },
    "tagline": "You Know, for Search"
}

RESTful & JSON

REST 指的是一组架构约束条件和原则。满足这些约束条件和原则的应用程序或设计就是 RESTful。

几个应该知道的点:

  • POST 不是幂等性的,PUT 是幂等性的。POST 是创建,PUT 是更新。

RESTFul 是个比较抽象且需要理解的概念,建议多查阅相关资料,加深理解。

JSON: JavaScript Object Notation(JavaScript 对象表示法)

  • JSON 是存储和交换文本信息的语法,类似 XML。
  • JSON 比 XML 更小、更快,更易解析。
{
    
    
    "sites": [
    {
    
     "name":"百度" , "url":"www.baidu.com" }, 
    {
    
     "name":"google" , "url":"www.google.com" }, 
    {
    
     "name":"微博" , "url":"www.weibo.com" }
    ]
}

Postman / ApiPost

如果直接通过浏览器向 Elasticsearch 服务器发请求,那么需要在发送的请求中包含 HTTP 标准的方法,而 HTTP 的大部分特性且仅支持 GET 和 POST 方法。所以为了能方便地进行客户端的访问,可以使用 Postman 软件。

Postman 是一款强大的网页调试工具,提供功能强大的 Web API 和 HTTP 请求调试。

也推荐使用:ApiPost - API 文档、调试、Mock、测试一体化协作平台

后面我们向 ES 服务器发送请求都会使用以上两个工具。

索引操作

倒排索引(理解)

正排索引(传统):

id content
1001 my name is zhang san
1002 my name is li si

倒排索引:

keyword id
name 1001, 1002
zhang 1001

Elasticsearch 是面向文档型数据库,一条数据在这里就是一个文档。

为了方便理解,将 Elasticsearch 里存储文档数据和关系型数据库 MySQL 存储数据的概念进行一个类比:

Type 的概念已经被逐渐弱化:

  • Elasticsearch 6.X 中,一个 index 下已经只能包含一个 type
  • Elasticsearch 7.X 中,Type 的概念已经被删除了。

创建索引 - PUT

对比关系型数据库,创建索引就等同于创建数据库。

在 ApiPost 中,向 ES 服务器发 PUT 请求 : http://127.0.0.1:9200/shopping

请求后,服务器返回响应:

{
    
    
    "acknowledged": true, // 响应结果
    "shards_acknowledged": true, // 分片结果
    "index": "shopping" // 索引名称
}

后台日志:

[2022-03-09T21:41:00,928][INFO ][o.e.c.m.MetadataCreateIndexService] [air.local] [shopping] creating index, cause [api], templates [], shards [1]/[1], mappings

如果重复发 PUT 请求 : http://127.0.0.1:9200/shopping 添加索引,会返回错误信息:

{
    
    
	"error": {
    
    
		"root_cause": [
			{
    
    
				"type": "resource_already_exists_exception",
				"reason": "index [shopping/8g4CcOYrRneyo-XSmAFs1Q] already exists",
				"index_uuid": "8g4CcOYrRneyo-XSmAFs1Q",
				"index": "shopping"
			}
		],
		"type": "resource_already_exists_exception",
		"reason": "index [shopping/8g4CcOYrRneyo-XSmAFs1Q] already exists",
		"index_uuid": "8g4CcOYrRneyo-XSmAFs1Q",
		"index": "shopping"
	},
	"status": 400
}

查询单个索引 - GET

向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping

{
    
    
    "shopping": {
    
     // 索引名
        "aliases": {
    
    }, // 别名
        "mappings": {
    
    }, // 映射
        "settings": {
    
     // 设置
            "index": {
    
     // 设置 - 索引
                "creation_date": "1617861426847", // 设置 - 索引 - 创建时间
                "number_of_shards": "1", // 设置 - 索引 - 主分片数量
                "number_of_replicas": "1", // 设置 - 索引 - 主分片数量
                "uuid": "J0WlEhh4R7aDrfIc3AkwWQ", // 设置 - 索引 - 主分片数量
                "version": {
    
     // 设置 - 索引 - 主分片数量
                    "created": "7080099"
                },
                "provided_name": "shopping" // 设置 - 索引 - 主分片数量
            }
        }
    }
}

查询所有索引 - GET

向 ES 服务器发 GET 请求:http://127.0.0.1:9200/_cat/indices?v](http://127.0.0.1:9200/_cat/indices?v)

请求路径中的 _cat 表示查看的意思,indices 表示索引,所以整体含义就是查看当前 ES服务器中的所有索引,就好像 MySQL 中的 SHOW TABLES 的感觉,服务器响应结果如下 :

health status index    uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   shopping 8g4CcOYrRneyo-XSmAFs1Q   1   1          0            0       208b           208b
含义
health 当前服务器健康状态: green(集群完整) yellow(单点正常、集群不完整) red(单点不正常)
status 索引打开、关闭状态
index 索引名
uuid 索引统一编号
pri 主分片数量
rep 副本数量
docs.count 可用文档数量
docs.deleted 文档删除状态(逻辑删除)
store.size 主分片和副分片整体占空间大小
pri.store.size 主分片占空间大小

删除索引 - DELETE

向 ES 服务器发 DELETE 请求:http://127.0.0.1:9200/shopping

返回结果如下:

{
    
    
	"acknowledged": true
}

再次查看所有索引,GET http://127.0.0.1:9200/_cat/indices?v,返回结果如下:

health status index uuid pri rep docs.count docs.deleted store.size pri.store.size

文档基本操作

创建文档 - POST

假设索引已经创建好了,接下来我们来创建文档,并添加数据。

这里的文档可以类比为关系型数据库中的表数据,添加的数据格式为 JSON 格式。

Content-Type 选择 application/json

向 ES 服务器发 POST 请求:http://127.0.0.1:9200/shopping/_doc,请求体 JSON 内容为:

{
    
    
    "title":"小米手机",
    "category":"小米",
    "images":"http://www.gulixueyuan.com/xm.jpg",
    "price":3999.00
}

注意,此处发送请求的方式必须为 POST,不能是 PUT,否则会发生错误。

{
    
    
    "_index": "shopping", // 索引
    "_type": "_doc", // 类型-文档
    "_id": "ANQqsHgBaKNfVnMbhZYU", // 唯一标识,可以类比为 MySQL 中的主键,随机生成
    "_version": 1, // 版本
    "result": "created", // 结果,这里的 create 表示创建成功
    "_shards": {
    
     // 分片
        "total": 2, // 分片 - 总数
        "successful": 1, // 分片 - 总数
        "failed": 0 // 分片 - 总数
    },
    "_seq_no": 0,
    "_primary_term": 1
}

上面的数据创建后,由于没有指定数据唯一性标识(ID),默认情况下, ES 服务器会随机生成一个。

如果想要自定义唯一性标识,需要在创建时指定:http://127.0.0.1:9200/shopping/_doc/1001,请求体 JSON:

{
    
    
    "title":"小米手机",
    "category":"小米",
    "images":"http://www.gulixueyuan.com/xm.jpg",
    "price":3999.00
}

返回结果:

{
    
    
	"_index": "shopping",
	"_type": "_doc",
	"_id": "1001", // 自定义唯一标识
	"_version": 1,
	"result": "created",
	"_shards": {
    
    
		"total": 2,
		"successful": 1,
		"failed": 0
	},
	"_seq_no": 3,
	"_primary_term": 1
}

如果增加数据时明确数据主键,那么请求方式也可以为 PUT,没有明确必须为 POST

主键查询 - GET

查看文档时,需要指明文档的唯一性标识,类似于 MySQL 中数据的主键查询。

向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_doc/1001

返回结果如下:

这种查询方式只能查询一条数据。

{
    
    
	"_index": "shopping",
	"_type": "_doc",
	"_id": "1001",
	"_version": 4,
	"_seq_no": 6,
	"_primary_term": 1,
	"found": true,
	"_source": {
    
    
		"title": "小米手机",
		"category": "小米",
		"images": "http://www.gulixueyuan.com/xm.jpg",
		"price": 3999
	}
}

查询一个不存在的数据,向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_doc/1111

返回结果如下:

{
    
    
	"_index": "shopping",
	"_type": "_doc",
	"_id": "1111",
	"found": false
}

全查询 - GET

查看索引下所有数据,向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_search

返回结果如下:

{
    
    
	"took": 133,
	"timed_out": false,
	"_shards": {
    
    
		"total": 1,
		"successful": 1,
		"skipped": 0,
		"failed": 0
	},
	"hits": {
    
    
		"total": {
    
    
			"value": 3,
			"relation": "eq"
		},
		"max_score": 1,
		"hits": [
			{
    
    
				"_index": "shopping",
				"_type": "_doc",
				"_id": "AlsTb38BaAVJP39iKv8b",
				"_score": 1,
				"_source": {
    
    
					"title": "小米手机",
					"category": "小米",
					"images": "http://www.gulixueyuan.com/xm.jpg",
					"price": 3999
				}
			},
			{
    
    
				"_index": "shopping",
				"_type": "_doc",
				"_id": "1",
				"_score": 1,
				"_source": {
    
    
					"title": "小米手机",
					"category": "小米",
					"images": "http://www.gulixueyuan.com/xm.jpg",
					"price": 3999
				}
			},
			{
    
    
				"_index": "shopping",
				"_type": "_doc",
				"_id": "1001",
				"_score": 1,
				"_source": {
    
    
					"title": "小米手机",
					"category": "小米",
					"images": "http://www.gulixueyuan.com/xm.jpg",
					"price": 3999
				}
			}
		]
	}
}

全量修改 - PUT

由于是 全量修改,所以结果是幂等的,可以使用 PUT

和新增文档一样,输入相同的 URL 地址请求,如果请求体变化,会将原有的数据内容覆盖(全部信息)。

向 ES 服务器发 POST 请求:http://127.0.0.1:9200/shopping/_doc/1001

请求体的内容为:(全部信息将会被覆盖)

{
    
    
    "title":"华为手机",
    "category":"华为",
    "images":"http://www.gulixueyuan.com/hw.jpg",
    "price":1999.00
}

修改成功后,服务器响应结果:

{
    
    
	"_index": "shopping",
	"_type": "_doc",
	"_id": "1001",
	"_version": 5,
	"result": "updated", // 数据被更新
	"_shards": {
    
    
		"total": 2,
		"successful": 1,
		"failed": 0
	},
	"_seq_no": 7,
	"_primary_term": 1
}

局部修改 - POST

由于是 局部修改,不能保证幂等,所以使用 POST

修改数据时,也可以只修改某一给条数据的局部信息。

向 ES 服务器发 POST 请求:http://127.0.0.1:9200/shopping/_update/1001

请求体的 JSON:(只会修改局部信息)

{
    
    
	"doc": {
    
    
		"title":"小米手机",
		"category":"小米"
	}
}

返回结果:

{
    
    
	"_index": "shopping",
	"_type": "_doc",
	"_id": "1001",
	"_version": 6,
	"result": "updated", // 数据被更新
	"_shards": {
    
    
		"total": 2,
		"successful": 1,
		"failed": 0
	},
	"_seq_no": 8,
	"_primary_term": 1
}

删除 - DELETE

删除一个文档不会立即从磁盘上移除,它只是被标记成已删除(逻辑删除)。

向 ES 服务器发 DELETE 请求:http://127.0.0.1:9200/shopping/_doc/1001

返回结果:

{
    
    
	"_index": "shopping",
	"_type": "_doc",
	"_id": "1001",
	"_version": 7,
	"result": "deleted", // 删除成功
	"_shards": {
    
    
		"total": 2,
		"successful": 1,
		"failed": 0
	},
	"_seq_no": 9,
	"_primary_term": 1
}

文档查询操作 - GET

条件查询

URL 带参查询

示例:查找 category 为小米的文档

向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_search?q=category:小米

_search?q=key:value 表示以 key、value 的形式查询

URL 带参数形式查询,容易让不善者心怀恶意,或者参数值出现中文会出现乱码情况。为了避免这些情况,可以用使用带 JSON 请求体请求进行查询。

带请求体方式查询

示例:查找 category 为小米的文档

向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_search,附带 JSON 请求体如下:

{
    
    
	"query":{
    
    
		"match":{
    
    
			"category":"小米"
		}
	}
}

带请求体方式的查找所有内容

示例:查询所有文档内容。

向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_search,附带 JSON 请求体如下:

{
    
    
	"query":{
    
    
		"match_all":{
    
    }
	}
}

分页查询

示例:每页有 2 条数据,查询第 1 页的内容。

向 ES 服务器发 GET请求:http://127.0.0.1:9200/shopping/_search,附带 JSON 请求体如下:

{
    
    
	"query":{
    
    
		"match_all":{
    
    }
	},
	"from":0,
	"size":2
}

查询排序

示例:通过排序查出价格最高的手机。

向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_search,附带 JSON 请求体如下:

{
    
    
	"query":{
    
    
		"match_all":{
    
    }
	},
	"sort":{
    
    
		"price":{
    
    
			"order":"desc"
		}
	}
}

多条件查询

示例:查询出小米手机,并且价格为 3999 元。

向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_search,附带 JSON 请求体如下:

must 相当于 && 操作

{
    
    
	"query":{
    
    
		"bool":{
    
    
			"must":[{
    
    
				"match":{
    
    
					"category":"小米"
				}
			},{
    
    
				"match":{
    
    
					"price":3999.00
				}
			}]
		}
	}
}

示例:查询出小米或华为牌子的手机。

向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_search,附带 JSON 请求体如下:

should 相当于 || 操作

{
    
    
	"query":{
    
    
		"bool":{
    
    
			"should":[{
    
    
				"match":{
    
    
					"category":"小米"
				}
			},{
    
    
				"match":{
    
    
					"category":"华为"
				}
			}]
		}
	}
}

范围查询

MARK:这个查询有问题!!!!!!

示例:找出小米或华为的牌子,价格大于 2000 的手机。

向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_search,附带 JSON 请求体如下:

{
    
    
	"query":{
    
    
		"bool":{
    
    
			"should":[{
    
    
				"match":{
    
    
					"category":"小米"
				}
			},{
    
    
				"match":{
    
    
					"category":"华为"
				}
			}],
      "filter":{
    
    
        "range":{
    
    
          "price":{
    
    
            "gt":2000
          }
        }
      }
		}
	}
}

全文检索

match 是拆分后进行模糊查询。

示例:像搜索引擎那样,如品牌输入 “小华”,返回结果带回品牌有 “小米” 和 “华为” 的。

向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_search,附带 JSON 请求体如下:

{
    
    
	"query":{
    
    
		"match":{
    
    
			"category" : "小华"
		}
	}
}

完全匹配

match_phrase 是一个整体的模糊查询。

示例:输入 “小华” 只匹配 “小华” 相关的内容,而不是拿 “小” 和 “华” 去匹配。

向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_search,附带 JSON 请求体如下:

{
    
    
	"query":{
    
    
		"match_phrase":{
    
    
			"category" : "小华"
		}
	}
}

高亮查询

向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_search,附带 JSON 请求体如下

{
    
    
	"query":{
    
    
		"match":{
    
    
			"category" : "小米"
		}
	},
    "highlight":{
    
    
        "fields":{
    
    
            "category":{
    
    } // <----高亮这字段
        }
    }
}

响应结果:注意看 highlight 字段

{
    
    
	"took": 98,
	"timed_out": false,
	"_shards": {
    
    
		"total": 1,
		"successful": 1,
		"skipped": 0,
		"failed": 0
	},
	"hits": {
    
    
		"total": {
    
    
			"value": 2,
			"relation": "eq"
		},
		"max_score": 0.9400072,
		"hits": [
			{
    
    
				"_index": "shopping",
				"_type": "_doc",
				"_id": "AlsTb38BaAVJP39iKv8b",
				"_score": 0.9400072,
				"_source": {
    
    
					"title": "小米手机",
					"category": "小米",
					"images": "http://www.gulixueyuan.com/xm.jpg",
					"price": 3999
				},
				"highlight": {
    
    
					"category": [
						"<em>小</em><em>米</em>"
					]
				}
			}
		]
	}
}

聚合查询

聚合允许使用者对 es 文档进行统计分析,类似与关系型数据库中的 GROUP BY,当然还有很多其他的聚合,例如取最大值 max、平均值 avg 等等。

示例:按 price 字段进行分组

向 ES 服务器发 GET 请求:http://127.0.0.1:9200/shopping/_search,附带 JSON 请求体如下:

{
    
    
	"aggs":{
    
    //聚合操作
		"price_group":{
    
    //名称,随意起名
			"terms":{
    
    //分组
				"field":"price"//分组字段
			}
		}
	}
}

响应结果:

{
    
    
	"took": 3,
	"timed_out": false,
	"_shards": {
    
    
		"total": 1,
		"successful": 1,
		"skipped": 0,
		"failed": 0
	},
	"hits": {
    
    
		"total": {
    
    
			"value": 3,
			"relation": "eq"
		},
		"max_score": 1,
		"hits": [
			{
    
    
				"_index": "shopping",
				"_type": "_doc",
				"_id": "AlsTb38BaAVJP39iKv8b",
				"_score": 1,
				"_source": {
    
    
					"title": "小米手机",
					"category": "小米",
					"images": "http://www.gulixueyuan.com/xm.jpg",
					"price": 3999
				}
			},
			{
    
    
				"_index": "shopping",
				"_type": "_doc",
				"_id": "1",
				"_score": 1,
				"_source": {
    
    
					"title": "小米手机",
					"category": "小米",
					"images": "http://www.gulixueyuan.com/xm.jpg",
					"price": 3999
				}
			},
			{
    
    
				"_index": "shopping",
				"_type": "_doc",
				"_id": "1001",
				"_score": 1,
				"_source": {
    
    
					"title": "苹果手机",
					"category": "苹果",
					"images": "http://www.gulixueyuan.com/xm.jpg",
					"price": 4999
				}
			}
		]
	},
	"aggregations": {
    
    
		"price_group": {
    
    
			"doc_count_error_upper_bound": 0,
			"sum_other_doc_count": 0,
			"buckets": [
				{
    
    
					"key": 3999,
					"doc_count": 2
				},
				{
    
    
					"key": 4999,
					"doc_count": 1
				}
			]
		}
	}
}

上面返回结果会附带原始数据的。若想要不附带原始数据的结果,JSON 请求体如下:

{
    
    
	"aggs":{
    
    
		"price_group":{
    
    
			"terms":{
    
    
				"field":"price"
			}
		}
	},
    "size":0
}

响应结果:

{
    
    
	"took": 13,
	"timed_out": false,
	"_shards": {
    
    
		"total": 1,
		"successful": 1,
		"skipped": 0,
		"failed": 0
	},
	"hits": {
    
    
		"total": {
    
    
			"value": 3,
			"relation": "eq"
		},
		"max_score": null,
		"hits": []
	},
	"aggregations": {
    
    
		"price_group": {
    
    
			"doc_count_error_upper_bound": 0,
			"sum_other_doc_count": 0,
			"buckets": [
				{
    
    
					"key": 3999,
					"doc_count": 2
				},
				{
    
    
					"key": 4999,
					"doc_count": 1
				}
			]
		}
	}
}

查询映射

有了索引库,等于有了数据库中的 database。

接下来就需要建索引库 (index) 中的映射了,类似于数据库 (database) 中的表结构 (table)。

创建数据库表需要设置字段名称,类型,长度,约束等;索引库也一样,需要知道这个类型下有哪些字段,每个字段有哪些约束信息,这就叫做映射 (mapping)。

创建一个索引:

# PUT http://127.0.0.1:9200/user

创建映射:

# PUT http://127.0.0.1:9200/user/_mapping

{
    
    
    "properties": {
    
    
        "name":{
    
    
        	"type": "text",
        	"index": true
        },
        "sex":{
    
    
        	"type": "keyword", // 注意,无法模糊匹配
        	"index": true
        },
        "tel":{
    
    
        	"type": "keyword", // 注意,无法模糊匹配
        	"index": false // 注意,查询时会报错
        }
    }
}

追加数据:

#PUT http://127.0.0.1:9200/user/_create/1001

{
    
    
	"name":"小米",
	"sex":"男的",
	"tel":"1111"
}

示例:查询 name 含有 “小” 的数据:(可以查到结果)

#GET http://127.0.0.1:9200/user/_search

{
    
    
	"query":{
    
    
		"match":{
    
    
			"name":"小"
		}
	}
}

示例:查找 sex 含有 “男” 的数据:(查不到结果 )

# GET http://127.0.0.1:9200/user/_search

{
    
    
	"query":{
    
    
		"match":{
    
    
			"sex":"男"
		}
	}
}
  • 找不想要的结果,是因为创建映射时 “sex” 的类型为 keyword
  • keyword 必须完全匹配,“sex” 只能完全为 “男的”,才能得出原数据

查询电话:

# GET http://127.0.0.1:9200/user/_search

{
    
    
	"query":{
    
    
		"match":{
    
    
			"tel":"11"
		}
	}
}

返回结果如下:

{
    
    
    "error": {
    
    
        "root_cause": [
            {
    
    
                "type": "query_shard_exception",
                "reason": "failed to create query: Cannot search on field [tel] since it is not indexed.",
                "index_uuid": "ivLnMfQKROS7Skb2MTFOew",
                "index": "user"
            }
        ],
        "type": "search_phase_execution_exception",
        "reason": "all shards failed",
        "phase": "query",
        "grouped": true,
        "failed_shards": [
            {
    
    
                "shard": 0,
                "index": "user",
                "node": "4P7dIRfXSbezE5JTiuylew",
                "reason": {
    
    
                    "type": "query_shard_exception",
                    "reason": "failed to create query: Cannot search on field [tel] since it is not indexed.",
                    "index_uuid": "ivLnMfQKROS7Skb2MTFOew",
                    "index": "user",
                    "caused_by": {
    
    
                        "type": "illegal_argument_exception",
                        "reason": "Cannot search on field [tel] since it is not indexed."
                    }
                }
            }
        ]
    },
    "status": 400
}

报错是因为创建映射时 “tel” 的 “index” 为 false。

猜你喜欢

转载自blog.csdn.net/weixin_43734095/article/details/123391508