ES根底
概念
1.1 ElasticSearh是什么
Elasticsearch 是一个分布式可扩大的实时搜寻和剖析引擎,一个建设在全文搜索引擎 Apache Lucene(TM) 根底上的搜索引擎,被广泛应用于全文搜寻。
它能够疾速、实时地存储、搜寻和剖析大量数据。
1.2 利用场景
- 作为海量数据的存储工具(亿级),分布式实时文件存储,并将每一个字段都编入索引,使其能够被搜寻。
- 简单的数据分析(ELK技术,elasticsearch+logstash+kibana)
- 分布式搜索引擎。能够扩大到上百台服务器,解决PB级别的结构化或非结构化数据。
1.3 集群构造
假如集群中有3台es,1台主节点,2台从节点,创立索引的时候,定义了为这个索引创立3个分片shard,1个正本replica
- 这个索引一共有6个分片,3个shard分片集,每个shard有1个replica正本集,所以一共就有6个分片集
- shard和对应的replica是不会在同一台机器上的
- 主节点负责节点和索引的增删改查,并不解决文档级别的增删改查
1.4 集群原理
倒排索引
正排索引:通过ID映射到相应的记录。
倒排索引:就是关键词到文档 ID 的映射,每个关键词都对应着一系列的文件,这些文件中都呈现了关键词。
DocId | Doc |
---|---|
1 | 谷歌地图之父跳槽 Facebook |
2 | 谷歌地图之父加盟 Facebook |
3 | 谷歌地图创始人拉斯来到谷歌加盟 Facebook |
4 | 谷歌地图之父跳槽 Facebook 与 Wave 我的项目勾销无关 |
5 | 谷歌地图之父拉斯加盟社交网站 Facebook |
倒排索引:用户输出查问 Facebook
,搜寻零碎查找倒排索引,从中读出蕴含这个单词的文档,这些文档就是提供给用户的搜寻后果。
- 倒排索引中的所有词项对应一个或多个文档;
- 倒排索引中的词项依据字典程序升序排列
WordId | Word | DocIds |
---|---|---|
1 | 谷歌 | 1, 2, 3, 4, 5 |
2 | 地图 | 1, 2, 3, 4, 5 |
3 | 之父 | 1, 2, 4, 5 |
4 | 跳槽 | 1, 4 |
5 | 1, 2, 3, 4, 5 | |
6 | 加盟 | 2, 3, 5 |
7 | 创始人 | 3 |
8 | 拉斯 | 3, 5 |
9 | 来到 | 3 |
10 | 与 | 4 |
写入数据
- 客户端抉择一个 node 发送申请过来,这个 node 就是
coordinating node
(协调节点)。 coordinating node
对 document 进行路由,将申请转发给对应的 node(有 primary shard)。- 理论的 node 上的
primary shard
解决申请,而后将数据同步到replica node
。 coordinating node
如果发现primary node
和所有replica node
都搞定之后,就返回响应后果给客户端。
底层原理:
- 数据先写入内存 buffer,而后每隔 1s,将数据 refresh 到 os cache(操作系统缓存),到了 os cache 数据就能被搜寻到(所以咱们才说 es 从写入到能被搜寻到,两头有 1s 的提早)。
- 每隔 5s,将数据写入 translog 文件(这样如果机器宕机,内存数据全没,最多会有 5s 的数据失落),translog 大到肯定水平,或者默认每隔 30mins,会触发 commit 操作,将缓冲区的数据都 flush 到 segment file 磁盘文件中。
总结:
- es 是准实时的,
buffer
中的数据被 refresh 操作刷入os cache
中,这个数据才能够被搜寻到 - ES是可能会失落数据的:translog 先写入 os cache ,默认每5 秒刷一次到磁盘,如果此时机器挂了,会失落 5 秒钟的数据。
读数据
写申请是写入 primary shard,而后同步给所有的 replica shard;读申请能够从 primary shard 或 replica shard 读取,采纳的是随机轮询算法。
能够通过 doc id
来查问,会依据 doc id
进行 hash,从而判断出 doc id
要调配到哪个 shard 下面去,即从那个 shard 去查问。
- 客户端发送申请到任意一个 node,成为
coordinate node
。 coordinate node
对doc id
进行哈希路由,将申请转发到对应的 node,此时会应用round-robin
随机轮询算法,在primary shard
以及其所有 replica 中随机抉择一个,让读申请负载平衡。- 接管申请的 node 返回 document 给
coordinate node
。 coordinate node
返回 document 给客户端。
分片路由形式
分片的路由形式相似于redis的hash槽。
当要插入文档或者查问文档时,这个文档将存到哪个分片,查问的时候到哪个分片中去查问这个文档, 是依据hash取模实现的。
ES高可用
- es的分片shard和正本集replica,不会位于同一个es节点(es-node)。
- shard会主动把内容复制到replica
- es shard和replica的负载平衡路由是有es外部主动实现的,内部用户无感知。
ES扩容
ES扩容过程中,用户无需去关注分片具体是怎么迁徙到新es-node的, 整个过程主动实现的。
1.5 设计剖析
- 商品数据变动时,将变动同步到ES中
- 查问商品列表或搜寻商品时,从ES中查问数据
- 为了进步ES吞吐率和伸缩性以及高可用,须要搭建ES集群架构
- 为了方便管理和监控,须要可视化工具 es-head和kibana
应用思路:
- 商品数据变动时,将变动同步到es中
- 查问商品列表数据或搜寻商品时,从es中查问数据
- 为了进步es吞吐率和伸缩性以及高可用,咱们须要搭建一个es集群架构
- 为了方便管理和监控,咱们须要可视化工具es-head和kibana
存储概念
ES是面向文档(document oriented)的,它能够存储整个对象或文档(document)。
ES会索引(index)每个文档的内容使之能够被搜寻。
ES能够对文档(而非成行成列的数据)进行索引、搜寻、排序、过滤。
文档属性
- index:索引库,相似于关系型数据库里的“数据库”—它是咱们存储和索引关联数据的中央。
- _type:类型,相似于关系型数据库中表。能够是大写或小写,不能蕴含下划线或逗号。咱们将应用 employee 做为类型名。(ES7当前停用,固定为_doc)
- _id:与 _index 和 _type 组合时,就能够在ELasticsearch中惟一标识(相似于主键)一个文档。当创立一个文档,你能够自定义 _id ,也能够让Elasticsearch帮你主动生成。
- _uid:文档惟一标识(type#id)
- _source:文档原始数据
- _all:所有字段的连贯字符串
ES集群能够蕴含多个索引(indices)(数据库),每个索引蕴含多个文档(documents)(行),而后每个文档蕴含多个字段(Fields)(列)。
Mapping:定义索引下的字段解决规定,即索引如何建设、索引类型、是否保留原始索引 JSON 文档、是否压缩原始 JSON 文档、是否须要分词解决、如何进行分词解决等。
关系数据库(MYSQL) | 数据库DB | 表TABLE | 行ROW | 列Column | Schema |
---|---|---|---|---|---|
Elasticsearch | 索引库Indices (数据库) | 类型Types(表) | 文档Documents(行) | 字段Fields(列) | Mapping |
2. 索引创立
创立索引 PUT
申请地址:http://ip:端口/索引名称
留神:索引名称必须小写
示例:http://localhost:9200/goods_list
{ "settings":{ "number_of_shards":3, //分片数量 "number_of_replicas":1 //正本数量 }, "mappings":{ "properties":{ "id":{"type":"integer"}, "goods_name":{"type":"text"}, "goods_description":{"type":"text"}, "goods_info":{"type":"text"} } }}
增加数据
申请地址:http://ip:端口/索引名/_doc/商品id
留神:
- 增加数据时指定的某个字段不存在时,es会主动创立该字段
- 指定id,不存在则创立,存在则更新
指定ID创立数据:
PUT /goods_list/_doc/123{ "id": "123", "goods_name": "测试商品的名称", "goods_description": "测试商品的形容", "goods_info": "。。。"}
ES内置ID创立(主动生成_id)
POST /goods_list/_doc/{ "id": "123456", "goods_name": "ES内置ID创立数据", "goods_description": "应用ES外部进行文档数据ID的生成", "goods_info": "。。。"}
3. 查问数据
- 获取索引中所有文档:
GET /goods_list/_search{ "query": { "bool": { "must": [ { "match": { "goods_name": "测试商品的名称" } } ] } }}
- 指定ID查问
GET http://192.168.30.128:9201/goods_list/_doc/123
- 带条件查问
GET /goods_list/_search/{ "query": { "bool": { "must": [ { "match": { "goods_name": "ES内置ID创立数据" } }, { "match" : { "goods_description": "ES外部" } } ] } }}
- 查问局部字段
GET /{index}/{type}/{id}?_source=fullName,email
- 只返回文档内容,不要元数据
GET /{index}/{type}/{id}/_source
- 批量获取1
GET http://192.168.30.128:9201/_mget{ "docs": [ { "_index": "goods_list", "_type": "_doc", "_id": 123 }, { "_index": "goods_list", "_type": "_doc", "_id": 1, "_source": "email,age" } ]}
- 批量获取2
GET http://192.168.30.128:9201/goods_list/_doc/_mget{ "ids": [ "123", "1" ]}
- 分页搜寻
GET crm/_doc/_search?size=5 #查问5条GET goods_list/_doc/_search?size=5&from=5 #查问6-10GET goods_list/_doc/_search?size=5&from=10 #查问11-15
- 查问字符串
http://192.168.30.128:9201/goods_list/_doc/_search?q=goods_name:商品
4. 查问条件精讲
精准查问term
查问条件都在路由的_serach
上面进行,但能够多个条件进行组织和安顿。
term是代表齐全匹配,即不进行分词器剖析,文档中必须蕴含整个搜寻的词汇。
trem单值
字段只有一个值时候,用term关键词查问。
精准查问,不须要查问进行评分计算。constant_score示意非评分模式。
GET http://192.168.30.128:9200/good_list/_doc/_search { "query" : { "constant_score" : { "filter" : { "term" : { "biz_id" : "1909190023901225" } } } } }
terms多值
字段有一多个值时候,用terms关键词查问,后跟数组
{ "query":{ "terms":{ "biz_id":["1909190023901225"] } }}
constant_score
非评分模式查问:
{ "query" : { "constant_score" : { "filter" : { "terms" : { "biz_id" : ["1909190023901225","e1909190111365113"] } } } } }
多个字段查问:
{ "query": [{ "term": { "biz_id": "1909190023901225" } }, { "term": { "name": "sixstar" } }]}
匹配查问match
- match查问的时候,ES会依据你给定的字段提供适合的分析器,而term查问不会有分析器剖析的过程
- match查问相当于含糊匹配,只蕴含其中一部分关键词就行。
match
进行full text search或者exact value(非string字段或not_analyzed的字段),进行匹配
示例:查问字段merchant_id为2501的值,并按工夫倒序
{ "query": { "match": { "merchant_id": "2501" } }, "sort": [ { "trade_finished_time": { "order": "desc" } } ]}
match_all
匹配所有的, 当不给查问条件时,默认全查
{ "query": { "match_all": {} }}
multi_match
同时对查问的关键词,多个字段同时进行匹配,即多个字段是AND的关系
{ "query":{ "multi_match":{ "query":"2501", "fields":["merchant_id","_id"] } }}
在在fields中,按brandName(品牌名)、sortName(分类名)、productName(商品名)productKeyword(商品关键字),搜寻“牛仔 弹力”关键词,brandName源值、拼音值、关键字值都是100分,sortName源值、拼音值80分,productName源值60分,productKeyword值20分,分值由高到低优先级搜寻
{ "query": { "multi_match": { "query": "牛仔 弹力", "fields": [ "brandName^100", "brandName.brandName_pinyin^100", "brandName.brandName_keyword^100", "sortName^80", "sortName.sortName_pinyin^80", "productName^60", "productKeyword^20" ], "type": <multi-match-type>, "operator": "AND" } }}
match_phrase
match_phrase
查问剖析文本,并从剖析文本中创立短语查问。
相似 match 查问, match_phrase 查问首先将查问字符串解析成一个词项列表,而后对这些词项进行搜寻,但只保留那些蕴含 全副 搜索词项,且 地位与搜索词项雷同的文档
如下,查问 quick brown、quick brown fox、 brown fox能够查问到,quick fox 查问不到
{ "query": { "match_phrase": { "title": "quick brown fox" } } }
查问 a,b,a和b之间隔3个字符能够查问到,隔不是3个查问不到
{ "query":{ "match_phrase" :{ "query":"a,b", "slop":3 } }}
bool查问
bool查问蕴含四种操作符,别离是must,should,must_not,query。它们均是一种数组,数组外面是对应的判断条件
- must: 必须匹配,与and等价。并且参加计算分值
- filter: 过滤子句,必须匹配,但不参加计算分值
- must_not:必须不匹配,与not等价,常过滤子句用,但不参加计算分值
- should: 选择性匹配,至多满足一条,与 OR 等价。参加计算分值
{ "query" : { "filtered" : { "filter" : { "bool" : { "should" : [ { "term" : {"merchant_id" : 100}}, { "term" : {"pay_type" : "3"}} ], "must_not" : { "term" : {"trade_type" : "2"} } } } } } }
filter查问
过滤器,会查问对后果进行缓存,不会计算相关度,防止计算分值,执行速度十分快。
如下, 查问出status
为active
的状态
{ "query": { "bool": { "filter": { "term": { "status": "active" } } } }}
filter也常和range范畴查问一起联合应用,range范畴可供组合的选项
- gt : 大于
- lt : 小于
- gte : 大于等于
- lte :小于等于
如下,查问merchant_id值为2501下的交易数据
{ "query": { "bool": { "must": { "term": { "merchant_id": "2501" } }, "filter": { "range": { "trade_finished_time": { "from": "2019-09-01T00:00:00", "to": "2019-09-30T23:59:59" } } } } }}
must下匹配,filter进行过滤,range定义范畴
{ "query": { "bool": { "must": [ { "match": { "title": "Search" } }, { "match": { "content": "Elasticsearch" } } ], "filter": [ { "term": { "status": "1" } }, { "range": { "publish_date": { "gte": "2015-01-01" } } } ] } } }
常见查问场景
1、查问商户ID为3582,订单号为360102199003072618,按工夫范畴过滤,按下单工夫倒序,每次查问100条
{ "query": { "bool": { "must": [{ "term": { "merchant_id": "3582" } }, { "term": { "order_num": "360102199003072618" } }], "filter": [{ "range": { "order_time": { "from": "2019-11-01T17:00:00+08:00", "to": "2019-11-01T20:00:00+08:00" } } }] } }, "size": 100, "sort": [{ "order_time": "desc" }]}
5. 批改数据
POST /goods_list/_doc/123/_update{"doc": { "goods_name": "测试商品的名称Winner" }}
6. 删除数据
DELETE /goods_list/_doc/123