Elasticsearch核心技术(二):Elasticsearch入门
2021/8/19 23:35:54
本文主要是介绍Elasticsearch核心技术(二):Elasticsearch入门,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
本文从基本概念、基本CRUD操作、倒排索引原理、分词等部分来初识Elasticsearch。
2.1 基本概念
Elasticsearch是面向文档(Document)的,文档是所有可搜索数据的最小单位;文档会被序列化成Json格式,保存在Elasticsearch中,并且每个文档都有一个唯一ID,可以通过Elasticsearch自动生成,也可以自己进行指定。对比MySQL,每行数据都有一个主键,这个主键可以使用MySQL自增主键,也可以通过雪花算法等方式生成然后进行自己设置。
文档的元数据,用于标注文档的相关信息。例如:_index表示文档所属的索引名,_id表示文档唯一ID,_score表示相关性打分,_source是文档的原始Json数据等。
索引(Index)是文档的容器,是一类文档的集合。对比MySQL,可以认为索引为一个数据表。
Mapping用来定义字段名和类型,对比MySQL,每个表有表结构的定义,包括字段名称,字段类型等。与关系型数据库进行类比:
RDBMS | Elasticsearch |
---|---|
Table | Index |
Row | Document |
Column | Field |
Schema | Mapping |
SQL | DSL |
节点是一个Elasticsearch的实例,本质上是一个Java进程。一台机器上可以运行多个Elasticsearch进程,但是生产环境一般建议一台机器上值运行一个Elasticsearch实例。节点分为数据节点和协调节点。数据节点是保存数据的节点,协调节点负责接收Client的请求,将请求路由到到合适的节点,并将结果汇集到一起。
集群是有多个节点组成的。
分片分为主分片和副本,每个分片可以设置一定数量的副本。主分片用于解决数据的水平扩展问题,通过主分片可以将数据分布到集群内的所有节点上。副本是用来解决数据高可用的问题,副本是主分片的拷贝,副本分片数可以动态调整,增加副本数,可以在一定程度上提高服务的可用性。当然副本可以提供查询功能,分摊系统的读负载。例如下图中,分片数为3,副本数为1。
对于分片的设定,生产环境中分片的设定需要提前进行规划。分片数量设置过小会导致后续无法增加节点实现水平扩展;而单个分片数据量太大,会导致数据重新分片耗时。分片数设置过大,会影响搜索结果的相关性打分,影响统计结果的准确性;而单个节点上有过多的分片,会导致资源浪费,同时会影响性能。
2.2 基本CRUD操作与批量操作
Elasticsearch对外提供RESTful API用于CRUD。使用RESTful API与Elasticsearch进行交互有两种方式:curl命令行和Kibana DevTools。可以直接使用Kibana DevTool与Elasticsearch进行交互。
2.2.1 索引操作
- 创建索引
request:PUT /test_index
response:
{ "acknowledged" : true, "shards_acknowledged" : true, "index" : "test_index" }
-
查看现有索引
request:GET _cat/indices
response:green open test_index GRXXECvrQjuNKRog7aDkPQ 1 1 2 3 28.9kb 14.4kb
-
删除索引
request:DELETE /test_index
response:
{ "acknowledged" : true }
2.2.2 文档操作
- 指定id创建文档
request:
PUT /test_index/_doc/1 { "username":"Paul", "age":10 }
response:
{ "_index" : "test_index", "_type" : "_doc", "_id" : "1", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 2, "failed" : 0 }, "_seq_no" : 0, "_primary_term" : 1 }
- 不指定id创建文档
request:
POST /test_index/_doc { "username":"Rose", "age":11 }
response:
{ "_index" : "test_index", "_type" : "_doc", "_id" : "soOv1HcB4Isa6tvVdQ9J", "_version" : 1, "result" : "created", "_shards" : { "total" : 2, "successful" : 2, "failed" : 0 }, "_seq_no" : 1, "_primary_term" : 1 }
- 指定id查询文档
request:GET /test_index/_doc/1
response:
{ "_index" : "test_index", "_type" : "_doc", "_id" : "1", "_version" : 1, "_seq_no" : 0, "_primary_term" : 1, "found" : true, "_source" : { "username" : "Paul", "age" : 10 } }
- 查询所有文档
request:GET /test_index/_search
response:
{ "took" : 2, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "test_index", "_type" : "_doc", "_id" : "1", "_score" : 1.0, "_source" : { "username" : "Paul", "age" : 10 } }, { "_index" : "test_index", "_type" : "_doc", "_id" : "soOv1HcB4Isa6tvVdQ9J", "_score" : 1.0, "_source" : { "username" : "Rose", "age" : 11 } } ] } }
- 更新文档
request:
POST /test_index/_update/1 { "doc": { "username": "Paul", "age": 20 } }
response:
{ "_index" : "test_index", "_type" : "_doc", "_id" : "1", "_version" : 2, "result" : "updated", "_shards" : { "total" : 2, "successful" : 2, "failed" : 0 }, "_seq_no" : 2, "_primary_term" : 1 }
- 删除文档
request:DELETE /test_index/_doc1
2.2.3 批量操作
批量操作可以减少网络连接所产生的开销,提高性能。
- _bulk
支持在一次API调用中,对不同的索引进行操作。
bulk支持Index、Create、Update?Delete四种操作。
请求中单条操作失败,并不会影响其他操作,返回结果中包含每一条操作的执行结果。
request:
POST _bulk {"index":{"_index":"test_index", "_id":"1"}} {"username":"Smart", "age":22} {"delete":{"_index":"test_index", "_id":"2"}}
response:
{ "took" : 95, "errors" : false, "items" : [ { "index" : { "_index" : "test_index", "_type" : "_doc", "_id" : "1", "_version" : 5, "result" : "updated", "_shards" : { "total" : 2, "successful" : 2, "failed" : 0 }, "_seq_no" : 5, "_primary_term" : 1, "status" : 200 } }, { "delete" : { "_index" : "test_index", "_type" : "_doc", "_id" : "2", "_version" : 1, "result" : "not_found", "_shards" : { "total" : 2, "successful" : 2, "failed" : 0 }, "_seq_no" : 6, "_primary_term" : 1, "status" : 404 } } ] }
- 批量读取mget
request:
GET _mget { "docs":[ { "_index":"test_index", "_id":1 }, { "_index":"movies", "_id":1 }] }
response:
{ "docs" : [ { "_index" : "test_index", "_type" : "_doc", "_id" : "1", "_version" : 2, "_seq_no" : 2, "_primary_term" : 1, "found" : true, "_source" : { "username" : "Paul", "age" : 20 } }, { "_index" : "movies", "_type" : "_doc", "_id" : "1", "_version" : 1, "_seq_no" : 6, "_primary_term" : 1, "found" : true, "_source" : { "id" : "1", "title" : "Toy Story", "year" : 1995, "genre" : [ "Adventure", "Animation", "Children", "Comedy", "Fantasy" ], "@version" : "1" } } ] }
- 批量查询msearch
request:
POST test_index/_msearch {} {"query":{"match_all":{}},"size":1} {"index":"kibana_sample_data_flights"} {"query":{"match_all":{}},"size":2}
response:
{ "took" : 4, "responses" : [ { "took" : 2, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 2, "relation" : "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "test_index", "_type" : "_doc", "_id" : "soOv1HcB4Isa6tvVdQ9J", "_score" : 1.0, "_source" : { "username" : "Rose", "age" : 11 } } ] }, "status" : 200 }, { "took" : 4, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 10000, "relation" : "gte" }, "max_score" : 1.0, "hits" : [ { "_index" : "kibana_sample_data_flights", "_type" : "_doc", "_id" : "iTmvUXcBNxIYppLoFWwg", "_score" : 1.0, "_source" : { "FlightNum" : "R3J7URU", "DestCountry" : "US", "OriginWeather" : "Hail", "OriginCityName" : "Moscow", "AvgTicketPrice" : 1172.5681640799792, "DistanceMiles" : 5149.888524287689, "FlightDelay" : false, "DestWeather" : "Rain", "Dest" : "Spokane International Airport", "FlightDelayType" : "No Delay", "OriginCountry" : "RU", "dayOfWeek" : 6, "DistanceKilometers" : 8287.942197231247, "timestamp" : "2021-02-14T10:59:03", "DestLocation" : { "lat" : "47.61989975", "lon" : "-117.5339966" }, "DestAirportID" : "GEG", "Carrier" : "ES-Air", "Cancelled" : false, "FlightTimeMin" : 753.4492906573861, "Origin" : "Sheremetyevo International Airport", "OriginLocation" : { "lat" : "55.972599", "lon" : "37.4146" }, "DestRegion" : "US-WA", "OriginAirportID" : "SVO", "OriginRegion" : "RU-MOS", "DestCityName" : "Spokane", "FlightTimeHour" : 12.557488177623101, "FlightDelayMin" : 0 } }, { "_index" : "kibana_sample_data_flights", "_type" : "_doc", "_id" : "ijmvUXcBNxIYppLoFWwg", "_score" : 1.0, "_source" : { "FlightNum" : "OE9TTXI", "DestCountry" : "GB", "OriginWeather" : "Sunny", "OriginCityName" : "Guangzhou", "AvgTicketPrice" : 834.6361636829536, "DistanceMiles" : 5911.063226254684, "FlightDelay" : false, "DestWeather" : "Thunder & Lightning", "Dest" : "London Heathrow Airport", "FlightDelayType" : "No Delay", "OriginCountry" : "CN", "dayOfWeek" : 6, "DistanceKilometers" : 9512.93413679362, "timestamp" : "2021-02-14T08:13:00", "DestLocation" : { "lat" : "51.4706", "lon" : "-0.461941" }, "DestAirportID" : "LHR", "Carrier" : "JetBeats", "Cancelled" : true, "FlightTimeMin" : 500.68074404176946, "Origin" : "Guangzhou Baiyun International Airport", "OriginLocation" : { "lat" : "23.39240074", "lon" : "113.2990036" }, "DestRegion" : "GB-ENG", "OriginAirportID" : "CAN", "OriginRegion" : "SE-BD", "DestCityName" : "London", "FlightTimeHour" : 8.344679067362824, "FlightDelayMin" : 0 } } ] }, "status" : 200 } ] }
2.3 倒排索引
2.3.1 正排索引与倒排索引
什么是正排索引?正排索引指的是从文档Id到文档内容、单词的关联关系。例如每本书的目录,通过目录可以很快找到某个标题的具体内容在书中的那一页。
什么是倒排索引?倒排索引指的文档内容或者单词到文档Id的关联关系。还是以书的例子,倒排索引指的是从具体内容到文章标题的索引。
知乎上面有人举了一个形象的例子。比如说考我们一首诗,给一首诗的名字,通常大家都可以背下来诗的内容。那为什么“飞花令”的时候我们想不起来诗句呢?因为我们的大脑中没有建立从诗句中某个字到诗名的倒排索引,假如说建立了这样的倒排索引,我们也可以像中国诗词大会的选手一样飞来飞去。
文档ID | 文档内容 |
---|---|
1 | Elasticsearch是最流行的搜索引擎 |
2 | Java是世界上最好的语言 |
3 | Google是全球最大的搜索引擎 |
单词 | 文档ID列表 |
---|---|
elasticsearch | 1 |
流行 | 1 |
搜索引擎 | 1,3 |
java | 2 |
世界 | 2 |
最好 | 2 |
语言 | 2 |
3 | |
全球 | 3 |
最大 | 3 |
Elasticsearch存储的是一个json格式的文档,其中包含多个字段,每个字段都会有自己的倒排索引。
那倒排索引是如何产生的呢?是文档内容分词之后和文档ID进行关联。
2.4 分词
分词是指将连续的字符串按照一定的规则重新切分成为单词(term or token)的过程,在ES里面叫做Analysis。
2.4.1 ES分词器组成和自带分词器
Analyzer是ES中专门处理分词的组件,组成如下:
- Character Filters:针对原始文本进行处理,比如去除HTML特殊标识符等
- Tokenizer:将原始文本按照一定规则切分成为单词
- Token Filters:针对Tokenizer处理的单词进行再加工,比如转小写、删除停用词或者新增同义词等处理
其工作过程如图所示:
Elasticsearch内置分词器
分词器 | 说明 |
---|---|
Standard Analyzer | 默认分词器,按词切分,小写处理,停用词处理默认关闭 |
Simple Analyzer | 按照非字母切分,非字母的都被去除,小写处理 |
Stop Analyzer | 小写处理,停用词过滤 |
Whitespace Analyzer | 按照空格切分,不转小写 |
Keyword Analyzer | 不分词,直接将输入内容进行输出 |
Pattern Analyzer | 正则表达式,默认\W+(非字母符号分割) |
Language | 提供30多种常见语言的分词器 |
Customer Analyzer | 自定义分词器 |
测试一下:
- 直接指定Analyzer进行测试
GET /_analyze { "analyzer": "standard", "text": [ "Hello World, Hello Elasticsearch" ] }
- 指定索引的字段进行测试
POST /movies/_analyze { "field": "title", "text": [ "Hello World, Hello Elasticsearch" ] }
- 自定义分词器进行测试
POST /_analyze { "tokenizer": "standard", "filter": [ "lowercase" ], "text": [ "Hello World, Hello Elasticsearch" ] }
2.4.2 Analyze API使用
ES提供一个测试分词的API接口,方便验证分词效果。_analyze
可以直接指定analyzer进行测试
可以直接指定索引中的字段进行测试:GET test_index/_analyze
可以自定义分词器进行测试
至此,学习了基本API的使用、批量操作、倒排索引原理和分词等概念,对ELasticsearch有了初步的认识。
这篇关于Elasticsearch核心技术(二):Elasticsearch入门的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-29怎么去掉UniApp中字符串的空格?-icode9专业技术文章分享
- 2024-11-29Warning: Cannot modify header information - headers already sent by 报错信息是什么?-icode9专业技术文章分享
- 2024-11-29Excel中实现拖动排序的简易教程
- 2024-11-29如何在Excel中使用拖动排序功能
- 2024-11-28阿里云 ECS课程:新手入门教程
- 2024-11-27Excel中实现拖动排序的简单教程
- 2024-11-27Rocket消息队列资料:新手入门指南
- 2024-11-27rocket消息队资料详解与入门指南
- 2024-11-27RocketMQ底层原理资料详解入门教程
- 2024-11-27RocketMQ项目开发资料:新手入门教程