欢迎光临
我们一直在努力

Elasticsearch相关特性

admin阅读(8)

一、ES分布式的特性
1.对复杂分布式机制的透明隐藏特性:
分片机制
集群发现机制
shard负载均衡
shard副本
请求路由
集群扩容
shard重分配
2.增减或减少节点时的数据rebalance
保持负载均衡
3.master节点
创建或删除索引
增加或删除节点
4.节点对等的分布式架构
节点对等,每个节点都能接收所有的请求
自动请求路由
响应收集
二、shard和replica机制
①index包含多个shard
②每个shard都是一个最小工作单元,承载部分数据,lucene实例,完整的建立索引和处理请求的能力
③增减节点时,shard会自动在nodes中负载均衡
④primary shard和replica shard,每个document肯定只存在于某一个primary shard以及其对应的replica shard中,不可能存在于多个primary shard
⑤replica shard是primary shard的副本,负责容错,以及承担读请求负载
⑥primary shard的数量在创建索引的时候就固定了,replica shard的数量可以随时修改
⑦primary shard的默认数量是5,replica默认是1。默认有10个shard,5个primary shard,5个replica shard
⑧primary shard不能和自己的replica shard放在同一个节点上(否则节点宕机,primary shard和副本都丢失,起不到容错的作用),但是可以和其他primary shard的replica shard放在同一个节点上
三、ES的横向扩容
①考虑提升系统整体吞吐量
②提高容错性,让尽可能多的服务器宕机,保证数据不丢失
四、宕机后的ES容错机制
①自动master选举,状态变为red
②replica容错:新master将replica提升为primary shard,状态变为yellow
③数据恢复:重启宕机node,master copy replica到该node,使用原有的shard并同步宕机后的修改,状态变为green

Elasticsearch数据建模

admin阅读(18)

1.将所有有关联关系的数据,放在一个doc json类型数据中。冗余数据,将可能会进行搜索的条件和要搜索的数据,放在一个doc中。一般来说,对于es这种NoSQL类型的数据存储来讲,都是冗余模式
{
“deptId”: “1”,
“name”: “研发部门”,
“desc”: “负责公司的所有研发项目”,
“employees”: [
{
“empId”: “1”,
“name”: “张三”,
“age”: 28,
“gender”: “男”
},
{
“empId”: “2”,
“name”: “王兰”,
“age”: 25,
“gender”: “女”
}
]
}
优点:性能高,不需要执行两次搜索
缺点:数据冗余,维护成本高 
2.在构造数据模型的时候,将有关联关系的数据,然后分割为不同的实体
PUT /website/users/1 
{
 “name”:     “小鱼儿”,
 “email”:    “xiaoyuer@sina.com”,
 “birthday”:      “1980-01-01”
}
PUT /website/blogs/1
{
 “title”:    “我的第一篇博客”,
 “content”:     “这是我的第一篇博客,开通啦!!!”
 “userId”:     1 
}
优点:数据不冗余,维护方便
缺点:应用层join,如果关联数据过多,导致查询过大,性能很差
3.基于nested object实现博客与评论嵌套关系
修改mapping,将comments的类型从object设置为nested
PUT /website
{
 “mappings”: {
“blogs”: {
 “properties”: {
“comments”: {
 “type”: “nested”, 
 “properties”: {
“name”:    { “type”: “string”  },
“comment”: { “type”: “string”  },
“age”:     { “type”: “short”   },
“stars”:   { “type”: “short”   },
“date”:    { “type”: “date”    }
 }
}
 }
}
 }
}
  基于nested object中的数据进行聚合分析:
  GET /website/blogs/_search 
{
 “size”: 0,
 “aggs”: {
“comments_path”: {
 “nested”: {
“path”: “comments”
 },
 “aggs”: {
“group_by_comments_age”: {
 “histogram”: {
“field”: “comments.age”,
“interval”: 10
 },
 “aggs”: {
“reverse_path”: {
 “reverse_nested”: {}, 
 “aggs”: {
“group_by_tags”: {
 “terms”: {
“field”: “tags.keyword”
 }
}
 }
}
 }
}
 }
}
 }
}
4.父子关系数据模型
相对于nested数据模型来说,优点是父doc和子doc互相之间不会影响
要点:父子关系元数据映射,用于确保查询时候的高性能,但是有一个限制,就是父子数据必须存在于一个shard中
例:PUT /company
{
 “mappings”: {
“rd_center”: {},
“employee”: {
 “_parent”: {
“type”: “rd_center” 
 }
}
 }
}
PUT /company/employee/1?parent=1 
{
 “name”:  “张三”,
 “birthday”:   “1970-10-24”,
 “hobby”: “爬山”
}
例:搜索有1980年以后出生的员工的研发中心:
GET /company/rd_center/_search
{
 “query”: {
“has_child”: {
 “type”: “employee”,
 “query”: {
“range”: {
 “birthday”: {
“gte”: “1980-01-01”
 }
}
 }
}
 }
}
例:搜索有至少2个以上员工的研发中心
GET /company/rd_center/_search
{
 “query”: {
“has_child”: {
 “type”:         “employee”,
 “min_children”: 2, 
 “query”: {
“match_all”: {}
 }
}
 }
}
例:搜索在中国的研发中心的员工:
GET /company/employee/_search 
{
 “query”: {
“has_parent”: {
 “parent_type”: “rd_center”,
 “query”: {
“term”: {
 “country.keyword”: “中国”
}
 }
}
 }
}
例:统计每个国家的喜欢每种爱好的员工有多少个
GET /company/rd_center/_search 
{
 “size”: 0,
 “aggs”: {
“group_by_country”: {
 “terms”: {
“field”: “country.keyword”
 },
 “aggs”: {
“group_by_child_employee”: {
 “children”: {
“type”: “employee”
 },
 “aggs”: {
“group_by_hobby”: {
 “terms”: {
“field”: “hobby.keyword”
 }
}
 }
}
 }
}
 }
}
5.祖孙三层数据模型
country -> rd_center -> employee
PUT /company
{
 “mappings”: {
“country”: {},
“rd_center”: {
 “_parent”: {
“type”: “country” 
 }
},
“employee”: {
 “_parent”: {
“type”: “rd_center” 
 }
}
 }
}
PUT /company/employee/1?parent=1&routing=1
routing参数必须跟grandparent相同
6.数据建模之悲观锁的并发控制,3种锁粒度
官方文档参考地址:
https://www.elastic.co/guide/cn/elasticsearch/guide/current/concurrency-solutions.html
①全局锁,直接锁掉整个fs index
PUT /fs/lock/global/_create
{}
DELETE /fs/lock/global
优点:操作非常简单,非常容易使用,成本低
缺点:你直接就把整个index给上锁了,这个时候对index中所有的doc的操作,都会被block住,导致整个系统的并发能力很低
②文档锁 document level锁
③共享锁:这份数据是共享的,然后多个线程过来,都可以获取同一个数据的共享锁,然后对这个数据执行读操作(读)
  排他锁:是排他的操作,只能一个线程获取排他锁,然后执行增删改操作(写)
  总结:如果只是要读取数据,任意个线程都可以同时进来然后读取数据,每个线程都可以上一个共享锁。
   如果有线程要过来修改数据,会尝试上排他锁,排他锁跟共享锁互斥,即,如果有人已经上了共享锁了,那么排他锁就不能上。
如果有人在读数据,就不允许别人来修改数据。反之,也是一样的。

Elasticsearch深入聚合数据分析

admin阅读(9)

一、聚合操作内部原理
1.正排索引(doc value)的聚合内部原理
①index-time生成
PUT/POST的时候,就会生成doc value数据,也就是正排索引
②核心原理与倒排索引类似
正排索引,也会写入磁盘文件中,然后os cache先进行缓存,以提升访问doc value正排索引的性能
如果os cache内存大小不足够放得下整个正排索引,doc value,就会将doc value的数据写入磁盘文件中
③性能问题:给jvm更少的内存,给os cache更大的内存
④如果的确不需要doc value,比如聚合等操作,那么可以禁用,减少磁盘空间占用
PUT my_index
{
  “mappings”: {
“my_type”: {
 “properties”: {
“my_field”: {
 “type”:       “keyword”
 “doc_values”: false 
}
 }
}
  }
}
⑤如果要对分词的field执行聚合操作,必须将fielddata设置为true
POST /test_index/_mapping/test_type 
{
  “properties”: {
“test_field”: {
 “type”: “text”,
 “fielddata”: true
}
  }
}
二、易并行聚合算法:比如max
1.近似聚合算法:采用在每个node上进行近估计的方式,得到最终的结论
如果采取近似估计的算法:延时在100ms左右,0.5%错误
如果采取100%精准的算法:延时一般在5s~几十s,甚至几十分钟,几小时,0%错误
2.三角选择原则:精准+实时+大数据 –> 选择2个
a.精准+实时: 没有大数据,数据量很小,那么一般就是单击跑,随便你则么玩儿就可以
b.精准+大数据:hadoop,批处理,非实时,可以处理海量数据,保证精准,可能会跑几个小时
c.大数据+实时:es,不精准,近似估计,可能会有百分之几的错误率
三、cardinality去重算法
cartinality metric,对每个bucket中的指定的field进行去重,取去重后的count,类似于count(distcint)
cardinality,count(distinct),5%的错误率,性能在100ms左右
cardinality算法,会占用precision_threshold * 8 byte 内存消耗,100 * 8 = 800个字节
HyperLogLog++ (HLL)算法性能优化
例:GET /tvs/sales/_search
{
 “size” : 0,
 “aggs” : {
 “months” : {
“date_histogram”: {
 “field”: “sold_date”,
 “interval”: “month”
},
“aggs”: {
 “distinct_colors” : {
 “cardinality” : {
“field” : “brand”
 }
 }
}
 }
 }
}
四、需求实战:记录下每次请求的访问的耗时,需要统计tp50,tp90,tp99
a.percentiles百分比算法
例:比如有一个网站,记录下了每次请求的访问的耗时,需要统计tp50,tp90,tp99
GET /website/logs/_search 
{
 “size”: 0,
 “aggs”: {
“group_by_province”: {
 “terms”: {
“field”: “province”
 },
 “aggs”: {
“latency_percentiles”: {
 “percentiles”: {
“field”: “latency”,
“percents”: [
 50,
 95,
 99
]
 }
},
“latency_avg”: {
 “avg”: {
“field”: “latency”
 }
}
 }
}
 }
}
b.percentile ranks和网站访问时延SLA统计
例:在200ms以内的,有百分之多少,在1000毫秒以内的有百分之多少
GET /website/logs/_search 
{
 “size”: 0,
 “aggs”: {
“group_by_province”: {
 “terms”: {
“field”: “province”
 },
 “aggs”: {
“latency_percentile_ranks”: {
 “percentile_ranks”: {
“field”: “latency”,
“values”: [
 200,
 1000
]
 }
}
 }
}
 }
}
c.percentile的优化:
TDigest算法:用很多节点来执行百分比的计算,近似估计,有误差,节点越多,越精准
compression:默认100,限制节点数量最多 compression * 20 = 2000个node去计算,越大,占用内存越多,越精准,性能越差,一个节点占用32字节,100 * 20 * 32 = 64KB,如果你想要percentile算法越精准,compression可以设置的越大
五、海量bucket优化机制:从深度优先到广度优先
例:对于评论数量排名前10的演员,每个演员的电影取到评论数量排名前5的电影
{
 “aggs” : {
“actors” : {
 “terms” : {
“field” :        “actors”,
“size” :         10,
“collect_mode” : “breadth_first” 
 },
 “aggs” : {
“costars” : {
 “terms” : {
“field” : “films”,
“size” :  5
 }
}
 }
}
}
}

深度优先的方式,构建了一整颗完整的树出来了,10万个actor,每个actor平均有10部电影,10万 + 100万 –> 110万的数据量的一颗树。构建了大量的数据,然后裁剪掉了99.99%的数据。
广度优先的方式,构建出film,裁剪出其中的5个film即可,10万 -> 50个

Elasticsearch中文分词器IK

admin阅读(9)

一、内置分词器的介绍
例:Set the shape to semi-transparent by calling set_trans(5)
standard analyzer(默认): set, the, shape, to, semi, transparent, by, calling, set_trans, 5
simple analyzer: set, the, shape, to, semi, transparent, by, calling, set, trans
whitespace analyzer: Set, the, shape, to, semi-transparent, by, calling, set_trans(5)
language analyzer: set, shape, semi, transpar, call, set_tran, 5
二、测试分词器
GET /_analyze
{
  “analyzer”: “standard”,
  “text”: “Text to analyze”
}
三、IK中文分词器
1.步骤:
git clone https://github.com/medcl/elasticsearch-analysis-ik
mvn package
将target/releases/elasticsearch-analysis-ik-*.*.*.zip拷贝到es/plugins/ik目录下
在es/plugins/ik下对elasticsearch-analysis-ik-*.*.*.zip进行解压缩
重启es

2.两种analyzer
ik_max_word: 会将文本做最细粒度的拆分
ik_smart: 会做最粗粒度的拆分
3.使用
PUT /my_index 
{
 “mappings”: {
“my_type”: {
 “properties”: {
“text”: {
 “type”: “text”,
 “analyzer”: “ik_max_word”
}
 }
}
 }
}
4.测试
GET /my_index/_analyze
{
 “text”: ” 对于你,我始终只能以陌生人的身份去怀念。”,
 “analyzer”: “ik_max_word”
}
5.配置文件
IKAnalyzer.cfg.xml:用来配置自定义词库
main.dic: ik原生内置的中文词库,总共有27万多条,只要是这些单词,都会被分在一起
quantifier.dic:放了一些单位相关的词
suffix.dic: 放了一些后缀
surname.dic: 中国的姓氏
stopword.dic: 英文停用词
6.添加自定义词库
IKAnalyzer.cfg.xml:ext_dict配置项,custom/mydict.dic
  添加自定义停用词库
IKAnalyzer.cfg.xml:ext_stopwords配置项,custom/ext_stopword.dic
7.热更新方案
第一种:修改ik分词器源码,然后手动支持从mysql中每隔一定时间,自动加载新的词库
①下载源码
https://github.com/medcl/elasticsearch-analysis-ik/tree/v6.2.4
②修改源码
Dictionary类,169行:Dictionary单例类的初始化方法,在这里需要创建一个我们自定义的线程,并且启动它
HotDictReloadThread类:就是死循环,不断调用Dictionary.getSingleton().reLoadMainDict(),去重新加载词典
Dictionary类,389行:this.loadMySQLExtDict();
Dictionary类,683行:this.loadMySQLStopwordDict();
③mvn package打包代码
target\releases\elasticsearch-analysis-ik-6.2.4.zip
④解压缩ik压缩包
将mysql驱动jar,放入ik的目录下
⑤将mysql驱动jar,放入ik的目录下
⑥修改jdbc相关配置
⑦重启es,观察日志
⑧在mysql中添加词库与停用词
⑨分词实验,验证热更新生效
(点击下载已修改好的zip包)
第二种:基于ik分词器原生支持的热更新方案,部署一个web服务器,提供一个http接口,通过modified和tag两个http响应头,来提供词语的热更新

Elasticsearch聚合数据分析

admin阅读(4)

1.两个核心概念
bucket:一个数据分组,类似数据库分组group by
metric:对一个数据分组执行的统计,常见的数据分析的metric操作有count,avg,max,min,sum
2.有分词的字段需要field的fielddata属性设置为true
PUT /ecommerce/_mapping/product
{
“properties”: {
“tags”: {
“type”: “text”,
“fielddata”: true
}
}
}
3.常用统计示例
例1.计算每个tag下的商品数量
GET /ecommerce/product/_search
{
“aggs”: {
“group_by_tags”: {
“terms”: { “field”: “tags” }
}
}
}
例2.对名称中包含yagao的商品,计算每个tag下的商品数量
GET /ecommerce/product/_search
{
“size”: 0,
“query”: {
“match”: {
“name”: “yagao”
}
},
“aggs”: {
“all_tags”: {
“terms”: {
“field”: “tags”
}
}
}
}
例3.先分组,再算每组的平均值,计算每个tag下的商品的平均价格
GET /ecommerce/product/_search
{
“size”: 0,
“aggs” : {
“group_by_tags” : {
“terms” : { “field” : “tags” },
“aggs” : {
“avg_price” : {
“avg” : { “field” : “price” }
}
}
}
}
}
例4.计算每个tag下的商品的平均价格,并且按照平均价格降序排序
GET /ecommerce/product/_search
{
“size”: 0,
“aggs” : {
“all_tags” : {
“terms” : { “field” : “tags”, “order”: { “avg_price”: “desc” } },
“aggs” : {
“avg_price” : {
“avg” : { “field” : “price” }
}
}
}
}
}
例5.按照指定的价格范围区间进行分组,然后在每组内再按照tag进行分组,最后再计算每组的平均价格
GET /ecommerce/product/_search
{
“size”: 0,
“aggs”: {
“group_by_price”: {
“range”: {
“field”: “price”,
“ranges”: [
{
“from”: 0,
“to”: 20
},
{
“from”: 20,
“to”: 40
},
{
“from”: 40,
“to”: 50
}
]
},
“aggs”: {
“group_by_tags”: {
“terms”: {
“field”: “tags”
},
“aggs”: {
“average_price”: {
“avg”: {
“field”: “price”
}
}
}
}
}
}
}
}
4.count、avg、max、min、sum
GET /tvs/sales/_search
{
“size” : 0,
“aggs”: {
“colors”: {
“terms”: {
“field”: “color”
},
“aggs”: {
“avg_price”: { “avg”: { “field”: “price” } },
“min_price” : { “min”: { “field”: “price”} },
“max_price” : { “max”: { “field”: “price”} },
“sum_price” : { “sum”: { “field”: “price” } }
}
}
}
}
5.使用内置field不分词,对string field进行聚合
GET /test_index/test_type/_search
{
“size”: 0,
“aggs”: {
“group_by_test_field”: {
“terms”: {
“field”: “test_field.keyword”
}
}
}
}
6.下钻:多层次的下钻,即分组再分组,多层嵌套聚合
例:每个颜色的电视中的品牌的数量和平均价格是多少
GET /tvs/sales/_search
{
“size”: 0,
“aggs”: {
“group_by_color”: {
“terms”: {
“field”: “color”
},
“aggs”: {
“color_avg_price”: {
“avg”: {
“field”: “price”
}
},
“group_by_brand”: {
“terms”: {
“field”: “brand”
},
“aggs”: {
“brand_avg_price”: {
“avg”: {
“field”: “price”
}
}
}
}
}
}
}
}
7.histogram:类似于terms,也是进行bucket分组操作,接收一个field,按照这个field的值的各个范围区间,进行bucket分组操作
例:GET /tvs/sales/_search
{
“size” : 0,
“aggs”:{
“price”:{
“histogram”:{
“field”: “price”,
“interval”: 2000
},
“aggs”:{
“revenue”: {
“sum”: {
“field” : “price”
}
}
}
}
}
}
8.date histogram,按照我们指定的某个date类型的日期field,以及日期interval,按照一定的日期间隔,去划分bucket
min_doc_count:区间无值补0
extended_bounds,min,max:划分bucket的时候,会限定在这个起始日期,和截止日期内
例:GET /tvs/sales/_search
{
“size” : 0,
“aggs”: {
“sales”: {
“date_histogram”: {
“field”: “sold_date”,
“interval”: “month”,
“format”: “yyyy-MM”,
“min_doc_count”: 0,
“extended_bounds” : {
“min” : “2016-01”,
“max” : “2017-12”
}
}
}
}
}
9.搜索结合聚合aggregation,scope
出来两个结果,一个结果,是基于query搜索结果来聚合的; 一个结果,是对所有数据执行聚合的
global:就是global bucket,就是将所有数据纳入聚合的scope,而不管之前的query
例:GET /tvs/sales/_search
{
“size”: 0,
“query”: {
“term”: {
“brand”: {
“value”: “长虹”
}
}
},
“aggs”: {
“single_brand_avg_price”: {
“avg”: {
“field”: “price”
}
},
“all”: {
“global”: {},
“aggs”: {
“all_brand_avg_price”: {
“avg”: {
“field”: “price”
}
}
}
}
}
}
global:就是global bucket,就是将所有数据纳入聚合的scope,而不管之前的query

Elasticsearch结构化搜索

admin阅读(7)

一、ES的cat api
查看mapping
GET /my_index/_mapping/my_type
检测健康状态
GET _cluster/health
操作索引:
PUT /test_index
DELETE /test_index
GET /test_index
操作文档:
PUT /index/type/id 数据已存在则覆盖
DELETE /index/type/id
POST /index/type/id/_update     更新
GET /index/type/id
注:document的全量替换和删除不会物理删除,只会将其标记为deleted,当数据越来越多的时候,才会在后台自动删除。更新也是这种逻辑。
二、简单案例:对商品进行增删改查
增:
PUT /ecommerce/product/1
{
“name” : “gaolujie yagao”,
“desc” :  “gaoxiao meibai”,
“price” :  30,
“producer” :      “gaolujie producer”,
“tags”: [ “meibai”, “fangzhu” ]
}
删:
DELETE /ecommerce/product/1
改:
POST /ecommerce/product/1/_update
{
“doc”: {
“name”: “jiaqiangban gaolujie yagao”
}
}
查:
GET /ecommerce/product/1
三、ES的搜索方式
数据准备:
PUT /ecommerce/product/1
{
“name” : “gaolujie yagao”,
“desc” :  “gaoxiao meibai”,
“price” :  30,
“producer” :      “gaolujie producer”,
“tags”: [ “meibai”, “fangzhu” ]
}
PUT /ecommerce/product/2
{
“name” : “jiajieshi yagao”,
“desc” :  “youxiao fangzhu”,
“price” :  25,
“producer” :      “jiajieshi producer”,
“tags”: [ “fangzhu” ]
}
PUT /ecommerce/product/3
{
“name” : “zhonghua yagao”,
“desc” :  “caoben zhiwu”,
“price” :  40,
“producer” :      “zhonghua producer”,
“tags”: [ “qingxin” ]
}
1.query string
例:
GET /ecommerce/product/_search
GET /ecommerce/product/_search?q=yagao
GET /ecommerce/product/_search?q=name:yagao
GET /ecommerce/product/_search?q=+name:yagao name必须包含yagao
GET /ecommerce/product/_search?q=-name:yagao name必须不包含yagao
GET /ecommerce/product/_search?q=name:yagao&sort=price:desc

 

 

 

 

 

 

 

 

 

 

 

解释:
took:耗费了几毫秒
timed_out:是否超时
_shards:数据拆成了5个分片,所以对于搜索请求,会打到所有的primary shard(或者是它的某个replica shard也可以)
hits.total:查询结果的数量,3个document
hits.max_score:document对于一个search的相关度的匹配分数,越相关,就越匹配,分数也高
hits.hits:包含了匹配搜索的document的详细数据
2.query DSL
例1:查全部:
GET /ecommerce/product/_search
{
“query”: { “match_all”: {} }
}
例2:查询名称包含yagao的商品,同时按照价格降序排序:
GET /ecommerce/product/_search
{
“query” : {
“match” : {
“name” : “yagao”
}
},
“sort”: [
{ “price”: “desc” }
]
}
例3:分页查询商品,总共3条商品,假设每页就显示1条商品,现在显示第2页,所以就查出来第2个商品
GET /ecommerce/product/_search
{
“query”: { “match_all”: {} },
“from”: 1,
“size”: 1
}
例4:指定查询结果字段,查询出商品的名称和价格
GET /ecommerce/product/_search
{
“query”: { “match_all”: {} },
“_source”: [“name”, “price”]
}
例5:多条件案例
每个子查询都会计算一个document针对它的相关度分数,然后bool综合所有分数,合并为一个分数,当然filter是不会计算分数的
GET /ecommerce/product/_search
{
“query”: {
“bool”: {
“must”: [
{
“match”: {
“name”: “yagao”
}
}
],
“should”: [
{
“match”: {
“desc”: “gaoxiao”
}
}
],
“must_not”: [
{
“match”: {
“price”: 40
}
}
]
}
}
}
3.query filter
例1:搜索商品名称包含yagao,而且售价大于25元的商品
GET /ecommerce/product/_search
{
“query” : {
“bool” : {
“must” : {
“match” : {
“name” : “yagao”
}
},
“filter” : {
“range” : {
“price” : { “gt” : 25 }
}
}
}
}
}
例2:搜索发帖日期在最近1个月的帖子
GET /forum/article/_search
{
“query”: {
“constant_score”: {
“filter”: {
“range”: {
“postDate”: {
“gt”: “now-30d”
}
}
}
}
}
}
4.full-text search(全文检索)
全文检索会将输入的搜索串拆解开来,去倒排索引里面去一一匹配,只要能匹配上任意一个拆解后的单词,就可以作为结果返回
例:
GET /ecommerce/product/_search
{
“query” : {
“match” : {
“producer” : “yagao producer”
}
}
}
5.phrase search(短语搜索)
跟全文检索相反,要求输入的搜索串,必须在指定的字段文本中,完全包含一模一样的,才可以算匹配,才能作为结果返回
例:
GET /ecommerce/product/_search
{
“query” : {
“match_phrase” : {
“producer” : “jiajieshi producer”
}
}
}
6.term query
term是字段的检索,检索时会按照你输入的内容按照完全匹配的模式检索
GET /ecommerce/product/_search
{
“query”: {
“term”: {
“producer”: “jiajieshi”
}
}
}
7.terms query
GET /ecommerce/product/_search
{
“query”: {
“terms”: {
“tags”: [
“search”,
“fangzhu”,
“zhongyao”
]
}
}
}
8.range query(范围查询)
GET /ecommerce/product/_search
{
“query”: {
“range”: {
“price”: {
“gte”: 30
}
}
}
}
9.multi match(多字段搜索)
GET /ecommerce/product/_search
{
“query”: {
“multi_match”: {
“query”: “producer”,
“fields”: [“producer”, “name”]
}
}
}
10.highlight search(高亮搜索)
例:
GET /ecommerce/product/_search
{
“query” : {
“match” : {
“producer” : “producer”
}
},
“highlight”: {
“fields” : {
“producer” : {}
}
}
}
四、mget批量查询
例1.同index不同type
GET /ecommerce/_mget
{
“docs” : [
{
“_type” :  “product”,
“_id” :    1
},
{
“_type” :  “product”,
“_id” :    2
}
]
}
例2.同index同type
GET /ecommerce/product/_mget
{
“ids”: [1, 2]
}
五、bulk批量增删改
1.删除一个文档
POST /_bulk
{ “delete”: { “_index”: “test_index”, “_type”: “test_type”, “_id”: “3” }}
2.强制创建
POST /_bulk
{ “create”: { “_index”: “test_index”, “_type”: “test_type”, “_id”: “12” }}
{ “test_field”:”test12″ }
3.创建文档或全量替换文档
POST /_bulk
{ “index”:  { “_index”: “test_index”, “_type”: “test_type”, “_id”: “2” }}
{ “test_field”:    “replaced test2” }
4.部分更新
POST /_bulk
{ “index”:  { “_index”: “test_index”, “_type”: “test_type”, “_id”: “2” }}
{ “test_field”:    “replaced test2” }
{ “update”: { “_index”: “test_index”, “_type”: “test_type”, “_id”: “1”, “_retry_on_conflict” : 3} }
{ “doc” : {“test_field2” : “bulk test1”} }
注:
①bulk api对json的语法,有严格的要求,每个json串不能换行,只能放一行,同时一个json串和一个json串之间,必须有一个换行
②bulk操作中,任意一个操作失败(多个增删改),是不会影响其他的操作的,但是在返回结果里会有异常日志信息
六、multi-index和multi-type搜索模式
/_search: 所有索引及该type下的所有数据都搜索出来
/index1/_search: 指定一个index,搜索其下所有type的数据
/index1,index2/_search:同时搜索两个index下的数据
/*1,*2/_search: 按照通配符去匹配多个索引
/index1/type1/_search: 搜索一个index下指定的type的数据
/index1/type1,type2/_search:可以搜索一个index下多个type的数据
/index1,index2/type1,type2/_search:搜索多个index下的多个type的数据
/_all/type1,type2/_search:_all代表搜索所有index下的指定type的数据
七、排序规则
1.默认排序规则:按照_score降序排序,某些情况下,可能没有有用的_score,比如说filter
2.按照constant_score(忽略评分)
GET /ecommerce/product/_search
{
“query” : {
“constant_score” : {
“filter” : {
“term” : {
“price” : 40
}
}
}
}
}
2.定制排序规则
GET /ecommerce/product/_search
{
“query”: {
“match_all”: {}
},
“sort”: {
“price”: {
“order”: “desc”
}
}
}
3. _doc
GET /ecommerce/product/_search
{
“query”: {
“match_all”: {}
},
“sort”: [“_doc”]
}
八、scoll滚动查询
1.用于大数据量查询,使用scoll滚动搜索,先搜索一批数据,然后下次再搜索一批数据,以此类推,直到搜索出全部的数据来
2.scoll搜索会在第一次搜索的时候,保存一个当时的视图快照,之后基于该旧的视图快照提供数据搜索,
3.采用基于_doc进行排序的方式,性能较高
4.每次发送scroll请求,需要指定一个scoll参数,指定一个时间窗口,每次搜索请求只要在这个时间窗口内能完成就可以了
5.例:
GET /test_index/test_type/_search?scroll=1m
{
“query”: {
“match_all”: {}
},
“sort”: [ “_doc” ],
“size”: 3
}
九、基于scoll+bulk+索引别名实现零停机重建索引
描述:重建一个索引,将旧索引的数据查询出来,再导入新索引中,java应用程序不需要停机,零提交,高可用。
①给java应用一个别名,这个别名是指向旧索引的,java应用先用着,java应用先用goods_index alias来操作,此时实际指向的是旧的my_index
PUT /my_index/_alias/goods_index
②新建一个index,调整field的类型等操作
③使用scroll api将数据批量查询出来
④采用bulk api将scoll查出的数据,批量写入新索引
⑤循环5~6到索引数据完成
⑥将goods_index alias切换到my_index_new上去,java应用会直接通过index别名使用新的索引中的数据
POST /_aliases
{
“actions”: [
{ “remove”: { “index”: “my_index”, “alias”: “goods_index” }},
{ “add”:    { “index”: “my_index_new”, “alias”: “goods_index” }}
]
}
⑦通过goods_index别名来查询
GET /goods_index/my_type/_search

Elasticsearch索引和Mapping

admin阅读(8)

一、索引
ES会自动建立index和type,不需要提前创建,而且es默认会对document每个field都建立倒排索引。

查看所有索引:

GET /_cat/indices?v

1.创建索引示例

PUT /my_index
{
	"settings": {
		"number_of_shards": 1,
		"number_of_replicas": 0
	},
	"mappings": {
		"my_type": {
			"properties": {
				"my_field": {
					"type": "text"
				}
			}
		}
	}
}

2.删除索引示例

DELETE /my_index
DELETE /index_one,index_two
DELETE /index_*
DELETE /_all

3.修改索引示例

PUT /my_index/_settings
{
"number_of_replicas": 1
}

二、ES的元数据
1. _index元数据
a.代表一个document存放在哪个index中
b.类似的数据放在一个索引,非类似的数据放不同索引:product index(包含了所有的商品),sales index(包含了所有的商品销售数据),inventory index(包含了所有库存相关的数据)。如果你把比如product,sales,human resource(employee),全都放在一个大的index里面,比如说company index,不合适的。
c.index中包含了很多类似的document,就是说这些document的fields很大一部分是相同的,你说你放了3个document,每个document的fields都完全不一样,这就不是类似了,就不太适合放到一个index里面去了。
d.索引名称必须是小写的,不能用下划线开头,不能包含逗号
2. _type元数据
a.代表document属于index中的哪个类别(type)
b.一个索引通常会划分为多个type,逻辑上对index中有些许不同的几类数据进行分类:因为一批相同的数据,可能有很多相同的fields,但是还是可能会有一些轻微的不同,可能会有少数fields是不一样的,举个例子,就比如说,商品,可能划分为电子商品,生鲜商品,日化商品,等等。
c.type名称可以是大写或者小写,但是同时不能用下划线开头,不能包含逗号
3. _id元数据
a.代表document的唯一标识,与index和type一起,可以唯一标识和定位一个document
b.两种生成方法,第一种手动指定document的id(put /index/type/id),第二种以由es自动为我们创建id(长度为20个字符,URL安全,base64编码,GUID算法,保证分布式系统并行生成时不会发生冲突)
4. _source元数据
a.定制返回的结果,指定_source中,返回哪些field
例:GET /test_index/test_type/1?_source=test_field1,test_field2
三、mapping
1.概述:
①自动或手动为index中的type建立的一种数据结构和相关配置,简称为mapping。
②可以在创建数据之前,手动先创建index和type,以及type对应的mapping,但是不能修改mapping。
③dynamic mapping,自动为我们建立index、type,以及type对应的mapping。
③mapping中包含了每个field对应的数据类型,以及如何分词等设置。
④不同的数据类型(比如说date和text),可能有的是exact value,有的是full text。
⑤mapping就是index的type的元数据,每个type都有一个自己的mapping,决定了数据类型,建立倒排索引的行为,进行搜索的行为。
⑥exact value,在建立倒排索引的时候,分词的时候,是将整个值一起作为一个关键词建立到倒排索引中的;full text,会经历各种各样的处理,分词,normaliztion(时态转换,同义词转换,大小写转换),才会建立到倒排索引中。
2.查看mapping
语法:

GET /index/_mapping/type

示例:GET /website/_mapping/article
3.创建mapping示例

PUT /website
{
	"mappings": {
		"article": {
			"properties": {
				"authorId": {
					"type": "long"
				},
				"title": {
					"type": "text",
					"fields": {
						"keyword": {
							"type": "keyword",
							"ignore_above": 50
						}
					}
				},
				"postDate": {
					"type": "date"
				}
			}
		}
	}
}

4.mapping的常用字段类型
string(5.0版本后拆分成两种数据类型text和keyword)
byte,short,integer,long
float,double
boolean
date
5.定制dynamic mapping策略
PUT /my_index

{
	"mappings": {
		"my_type": {
			"dynamic": "strict",
			"properties": {
				"title": {
					"type": "text"
				},
				"address": {
					"type": "object",
					"dynamic": "true"
				}
			}
		}
	}
}

true:默认,遇到陌生字段,就进行dynamic mapping
false:遇到陌生字段,就忽略
strict:遇到陌生字段,就报错

CentOS7.6.x分布式安装Elasticsearch7.6.1的详细步骤

admin阅读(45)

1、安装装备:

首先确认Linux版本,这里以CentOS7.6.1810为例,安装前请确保空间足够。

cat /etc/redhat-release

 

 

2、安装JDK环境,Elasticsearch要求JDK版本大于1.8,确保环境大于等于1.8即可。

java -version;

 

 

 

3、安装并启动Elasticsearch

curl -L -O https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.6.1-linux-x86_64.tar.gz
tar -xvf elasticsearch-7.6.1.tar.gz
cd elasticsearch-7.6.1/bin/
./elasticsearch

通过

curl -XGET '127.0.0.1:9200/_cat/health?v'

即可查看Elasticsearch启动状态

 

 

 

 

 

 

 

 

4、Elasticsearch分布式多节点配置,配置文件在 安装目录下面的 config 文件夹 

# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
#
cluster.name: jqm-elk
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
#
node.name: jqm-elk-1
#
# Add custom attributes to the node:
#
#node.attr.rack: r1

#是否是master节点
node.master: true
#是否允许该节点存储索引数据
node.data: true
#
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
network.host: 0.0.0.0
#
# Set a custom port for HTTP:
#
http.port: 9200

http.cors.enabled: true
#开启跨域访问后的地址限制,*表示无限制
http.cors.allow-origin: “*”

#
# For more information, consult the network module documentation.
#
# --------------------------------- Discovery ----------------------------------
#
# Pass an initial list of hosts to perform discovery when this node is started:
# The default list of hosts is ["127.0.0.1", "[::1]"]
#
discovery.seed_hosts: ["192.168.1.11", "192.168.1.12"]
#
# Bootstrap the cluster using an initial set of master-eligible nodes:
#
cluster.initial_master_nodes: ["jqm-elk-1"]

#集群内同时启动的数据任务个数,默认是2个
cluster.routing.allocation.cluster_concurrent_rebalance: 32
#添加或删除节点及负载均衡时并发恢复的线程个数,默认4个
cluster.routing.allocation.node_concurrent_recoveries: 32
#初始化数据恢复时,并发恢复线程的个数,默认4个
cluster.routing.allocation.node_initial_primaries_recoveries: 32
#
# For more information, consult the discovery and cluster formation module documentation.

从节点elasticsearch.yml配置配置文件配置

# ---------------------------------- Cluster -----------------------------------
#
# Use a descriptive name for your cluster:
#
cluster.name: jqm-elk
#
# ------------------------------------ Node ------------------------------------
#
# Use a descriptive name for the node:
#
node.name: jqm-elk-2
#
# Add custom attributes to the node:
#
#node.attr.rack: r1
#是否是master节点
node.master: false
#是否允许该节点存储索引数据
node.data: true
# ---------------------------------- Network -----------------------------------
#
# Set the bind address to a specific IP (IPv4 or IPv6):
#
network.host: 0.0.0.0
#
# Set a custom port for HTTP:
#
http.port: 9200
#
# For more information, consult the network module documentation.
#
# --------------------------------- Discovery ----------------------------------
#
# Pass an initial list of hosts to perform discovery when this node is started:
# The default list of hosts is ["127.0.0.1", "[::1]"]
#
discovery.seed_hosts: ["192.168.1.11", "192.168.1.12"]
#
# Bootstrap the cluster using an initial set of master-eligible nodes:
#
cluster.initial_master_nodes: ["jqm-elk-1"]

#集群内同时启动的数据任务个数,默认是2个
cluster.routing.allocation.cluster_concurrent_rebalance: 32
#添加或删除节点及负载均衡时并发恢复的线程个数,默认4个
cluster.routing.allocation.node_concurrent_recoveries: 32
#初始化数据恢复时,并发恢复线程的个数,默认4个
cluster.routing.allocation.node_initial_primaries_recoveries: 32
#
# For more information, consult the discovery and cluster formation module documentation.

 

5、Elasticsearch安装及常见问题解决办法

(1)错误:Exception in thread “main” java.lang.RuntimeException: don’t run elasticsearch as root。因为安全问题elasticsearch 不能用root用户直接运行,所以要创建新用户解决

useradd elk
chown -R elk:elk /home/elk/elasticsearch-7.6.1
su - elk -c "exec /home/elk/elasticsearch-7.6.1/bin/elasticsearch -d"

(2)提示:Max number of threads for elasticsearch too low
修改/etc/security/limits.conf

vim /etc/security/limits.conf

添加一行:

elk - nproc 2048

其中 elk 为用户名

(3)提示:max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]
修改/etc/sysctl.conf
vim /etc/sysctl.conf
添加一行:

vm.max_map_count=262144

添加完了执行:sysctl -p,看结果是不是vm.max_map_count = 262144

6、Elasticsearch配置文件详解

配置文件位于es根目录的config目录下面,配置文件是elasticsearch.yml,elasticsearch调用log4j记录日志,所以日志的配置文件可以按照默认的设置,我来介绍下elasticsearch.yml里面的选项。

cluster.name: node-1

配置的集群名称,默认是node-1,es服务会通过广播方式自动连接在同一网段下的es服务,通过多播方式进行通信,同一网段下可以有多个集群,通过集群名称这个属性来区分不同的集群。

node.name: "jqm-elk"

当前配置所在机器的节点名,你不设置就默认随机指定一个name列表中名字,该name列表在es的jar包中config文件夹里name.txt文件中,其中有很多作者添加的有趣名字。

node.master: true

指定该节点是否有资格被选举成为node(注意这里只是设置成有资格, 不代表该node一定就是master),默认是true,es是默认集群中的第一台机器为master,如果这台机挂了就会重新选举master。

node.data: true

指定该节点是否存储索引数据,默认为true。

index.number_of_shards: 5

设置默认索引分片个数,默认为5片。

index.number_of_replicas: 1

设置默认索引副本个数,默认为1个副本。如果采用默认设置,而你集群只配置了一台机器,那么集群的健康度为yellow,也就是所有的数据都是可用的,但是某些复制没有被分配(

健康度可用 curl ‘127.0.0.1:9200/_cat/health?v’ 查看, 分为绿色、黄色或红色。绿色代表一切正常,集群功能齐全,黄色意味着所有的数据都是可用的,但是某些复制没有被分配,红色则代表因为某些原因,某些数据不可用)。

path.conf: /path/to/conf

设置配置文件的存储路径,默认是es根目录下的config文件夹。

path.data: /path/to/data

设置索引数据的存储路径,默认是es根目录下的data文件夹,可以设置多个存储路径,用逗号隔开,例:

path.data: /path/to/data1,/path/to/data2

path.work: /path/to/work

设置临时文件的存储路径,默认是es根目录下的work文件夹。

path.logs: /path/to/logs

设置日志文件的存储路径,默认是es根目录下的logs文件夹

path.plugins: /path/to/plugins

设置插件的存放路径,默认是es根目录下的plugins文件夹, 插件在es里面普遍使用,用来增强原系统核心功能。

bootstrap.mlockall: true

设置为true来锁住内存不进行swapping。因为当jvm开始swapping时es的效率 会降低,所以要保证它不swap,可以把ES_MIN_MEM和ES_MAX_MEM两个环境变量设置成同一个值,并且保证机器有足够的内存分配给es。 同时也要允许elasticsearch的进程可以锁住内存,linux下启动es之前可以通过`ulimit -l unlimited`命令设置。

network.bind_host: 192.168.1.11

设置绑定的ip地址,可以是ipv4或ipv6的,默认为0.0.0.0,绑定这台机器的任何一个ip。network.publish_host: 192.168.1.11
设置其它节点和该节点交互的ip地址,如果不设置它会自动判断,值必须是个真实的ip地址。

network.host: 192.168.1.11

这个参数是用来同时设置bind_host和publish_host上面两个参数。

transport.tcp.port: 9300

设置节点之间交互的tcp端口,默认是9300。

transport.tcp.compress: true

设置是否压缩tcp传输时的数据,默认为false,不压缩。

http.port: 9200

设置对外服务的http端口,默认为9200。

http.max_content_length: 100mb

设置内容的最大容量,默认100mb

http.enabled: false

是否使用http协议对外提供服务,默认为true,开启。

gateway.type: local

gateway的类型,默认为local即为本地文件系统,可以设置为本地文件系统,分布式文件系统,hadoop的HDFS,和amazon的s3服务器等。

gateway.recover_after_nodes: 1

设置集群中N个节点启动时进行数据恢复,默认为1。

gateway.recover_after_time: 5m

设置初始化数据恢复进程的超时时间,默认是5分钟。

gateway.expected_nodes: 2

设置这个集群中节点的数量,默认为2,一旦这N个节点启动,就会立即进行数据恢复。

cluster.routing.allocation.node_initial_primaries_recoveries: 4

初始化数据恢复时,并发恢复线程的个数,默认为4。

cluster.routing.allocation.node_concurrent_recoveries: 2

添加删除节点或负载均衡时并发恢复线程的个数,默认为4。

indices.recovery.max_size_per_sec: 0

设置数据恢复时限制的带宽,如入100mb,默认为0,即无限制。

indices.recovery.concurrent_streams: 5

设置这个参数来限制从其它分片恢复数据时最大同时打开并发流的个数,默认为5。

discovery.zen.minimum_master_nodes: 1

设置这个参数来保证集群中的节点可以知道其它N个有master资格的节点。默认为1,对于大的集群来说,可以设置大一点的值(2-4)

discovery.zen.ping.timeout: 3s

设置集群中自动发现其它节点时ping连接超时时间,默认为3秒,对于比较差的网络环境可以高点的值来防止自动发现时出错。

discovery.zen.ping.multicast.enabled: false

设置是否打开多播发现节点,默认是true。

discovery.zen.ping.unicast.hosts: ["host1", "host2:port", "host3[portX-portY]"]

设置集群中master节点的初始列表,可以通过这些节点来自动发现新加入集群的节点。