elasticsearch -入门

https://blog.youkuaiyun.com/qq_26803795/article/details/81482856

1.倒排索引
类似于以下结构   
1 宋茂林的家人 
2 宋茂林的电影
3 宋茂林的狗
  关键字    ids
   宋茂林   123
  家人        1
  电影       2 
  狗狗        3
我们可以在建立倒排时候,把同义词等加入,复数转单数(normalization)

当我们检索时候  搜索宋茂林的猫,分成宋茂林 猫  ,在倒排索引重搜索,宋茂林找到123 猫没找到,返回的就是123的id数据。
比数据库的模糊查询效率高,我们这可能直接一次就查询出来了,数据库要全表扫。数据库也不能分词。

2 lucene
就是一个jar 包含了倒排索引的建立,搜索的code, 包括很多算法,可以把已有的数据建立索引,在本地磁盘上给我们组织索引的数据结

基于Lucene的
保证了数距的高可用,保证了索引的建立在多个节点上,查询时候也到各个节点查询。提供了一些高及查询,如查询地理位置1公里的烤肉
店。

分布式的搜索引引擎 数据分析引擎(销量前十的)

搜索:全文检索
         结构化检索(有过滤的等) 过滤的是一个结构
         等
         

3kibana
控制台 管理 es的,可提供各种数据, 如 集群的健康状态 indeies curd等  端口 5601

es端口9200
https://www.cnblogs.com/yiwangzhibujian/p/7137546.html


index  相当于 数据库
type  相当于表
document 相当于数据的一行

4crud
查询  get /index/type/1
创建  put  /index/type/1
   {结构化json数据}
修改  put /index/type/1{结构化json数据} 这样这个数据就被覆盖掉了 ,用put是替换json的数据
       post  /index/type/1/_update {"doc":{name:"sss"}}  这样是修改1的namefiled属性,其他属性还是以前的s
partial update
post /index/type/1/update{
   "doc":{feidl:value}
}
我们用 partial update 1.减少交互,前者的先查,再写,后者直接在es写,2减少并发冲突,前者查询在写时间长,后者在es操作毫秒级
当我们partial update修改时候 发现版本号小了(可能有其他的线程操作完成了),这个时候我们可以指定retry侧率,
retry_on_confilct=5,retry5次,或者手动指定version保证数据写入es中

删除 delete /index/type/1   只是一个标记删除  ,不是真的物理删除,当到阀值时候后台删除
修改删除 会增加version  这个用来保证数据的一致性的 ,多个节点赋值数据的时候。乐观锁

get  /_cat/health  jiancha集群的健康状态
get /jiqun名/indeies  查看索引
kibana 启动时候,在es上创建一个索引,用一个shard主一个shard从来存储,默认es一个索引是5个主5个从的。
当启动一个es节点时候,shard启动率50%,只有一个主,从没有

nrt 近实时 ,es存储数据默认1秒后才能查询到。

5搜索方式
query string  search  不会用
类似于url参数在?
全部查询
get  /index/type/_search
查询过滤
get  /index/type/_search?q=name:yaogao&sort=price:desc  
get  /index/type/_search?q=+name:yaogao 与上面的一致 必须包含
get  /index/type/_search?q=-name:yaogao  name列必须不包含yaogao  
get  /index/type/_search?q=test   不管哪个feild包含test 就返回,我们是对每个field都进行搜索妈,不是的,运用了_all这个元数
据。
_all:es创建一个document,吧所有的feild以字符串的形式拼接,形成一个新的字符串,这个字符串就是就是_all feild的值,建立倒排索
引,搜索时候没指定feild ,那么就查_all
query dsl  结构体查询
get  /index/type/_search

    “query”:{“match_all”:{}}

get /index/type/_search
{
  "query":{
                  "match":{"name":"yaogao"}
                },
  "sort":[{"price":"desc"}]
}
}
分页
from size 先搜索所有的  之后用from size限制 
get /index/type/_search

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

查询指定feild   _source

get /index/type/_search
{
  "query":{
                  "match":{"name":"yaogao"}
                },
  "_source":["name","price"] 
}

过滤  filter
多个查询条件应封装到bool的json中   bool 是组合查询
 get /index/type/_searche
{
   "query":{
        "bool":{
             "must":{
                  "match”:{"name":"yaogao"}
             },
             “filter”:{
                  "range":{
                       "price":{"gt","25"}
                   }
              }  
        }
    }

全文检索  把词分了  ,各个词都去指定的index索引指定的feidl 去匹配  ,由匹配度不同而返回不同的maxsroce
get  /index/type/_search
{
   "query":{
        "match":{
            producer:"yaogao prodces" 
        }
    }
}
全文检索会先把关键词分词

短语检索  match_phrase关键词不分词
get  /index/type/_search
{
 "query":{
     “match_phrase”:{
            producer:"yaogao prodces" 
        }
  }
}

高亮  highlighjt

group by 等聚合分析
1计算每个tag下的商品数量 aggs 聚合 terms 
get  /index/type/_search
{
  "aggs":{
     "group_by_tag":{
          "terms":{"field":"tag"}
       }
   }
}
执行这个语句会报错,提示要修改tag的filecdate属性为true
put /index/_mapping/type
{
    "properties":{
       "tags":{
           "type":"text",
          "fileddate":"true"
        }
     }
}
修改索引的mapping

聚合时候会把原始数据放到返回结果,我们设置“size”:0 ,可以吧原始数据过滤掉,与aggs 同级

先分组  计算每组平均值  avg 嵌套聚合
get  /index/type/_search
{
   size”:0,
    "aggs":{
        "group_by_tag":{
               "terms":{
                    "feild":"tags"
                 },
                  "aggs":{
                          "avg_price":{
                               "avg":{
                                    "feild":"price"
                                }
                            }
                   }
         }
    }
}

按照平均价格降序排序
get /index/type/_search

    "size":0,
    "aggs":{
         "group_by_tags":{
                “terms”:{
                       "feild":"tags",
                         "order":{
                           "avg_price":"desc"
                         }
                   },
                   “aggs”:{
                       “avg_price”:{
                             "feild":"price"
                          }
                  }
          }
     }

按照指定的价格范围区间进行分组,然后在每组内在按照tag进行分组,最后计算每组的平均价格
get  /index/type/_search{
   "size":0,
    "aggs":{
       ”group_by_price”:{
               “range”:{
                       "feild":"price",
                        "ranges":[
                             { "from":0,
                               "to":20
                             },
                            { "from":20,
                               "to":40
                             },
                            { "from":40,
                               "to":60
                             }
                         ]
                 },
               "aggs":{
                   "group_by_tags":{
                    “terms”:{
                        "feild":"tags",
                         "order":{
                           "avg_price":"desc"
                         }
                      },
                   “aggs”:{
                       “avg_price”:{
                             "feild":"price"
                          }
              }
          }
     }
        }
    }
}

-----------------------------------------------------------------------------------------------
6 es对分布式机制的隐藏特性
分片机制隐藏了,数据保存了,数据到底放到哪个shard,
新启动一个节点,这个节点是如何加到集群的?数据是如何放到这个新的节点的?
shard负载  有3个节点,25个shard(5个index),es吧这25geshard平均分到3个节点
数据读取时候,是如何请求有数据的节点的?

7扩容是怎们做的


8.节点增加减少时候 es 会rebalance
当节点新增了,es自动会吧原来节点放多个shard的,移动一些shard到新的节点,为了负载,这就是es 自动reblance

9master 节点 
https://blog.youkuaiyun.com/J_bean/article/details/80147277
master存储元数据,索引的创建删除,节点增加移除  。默认选出一个marster

---------------------------------------------------------------------------------------------

一个index包含一个或多个shard,每个shard放到不同节点上。
shard是数据最小的存储单元,每个shard就是luncen的实例,完成的建立索引数据请求的能力
增加删除节点,shard会自动的负载到节点上。
primary shard   replica shard 一个document只会存储在一个primary  shard里(和对应的replica shard)。不会存在于多个
primaryshard
primary shard 在创建索引时候就已经固定了,replica shard数量课修改
默认 5个primary  replica 1 意思就是5个prmaryshard  ,每个主都有一个replica  一共10个shard
每个primaryshard 不能与自己的replicashard放在一个节点上

单台node 创建index 什么样
创建索引3个primary shard 3个replica
put /index_name
{"setting":{
     "number_of_shards":3,
     "number_of_replica":1
   }
}
这时候直飞配3个primary  ,3个replica不分配的。

当一个节点加入,此时有2个节点
那么新增加的节点会有3个replicashard
在加一个节点 那么可能把第一个节点的 p1 放到新增的节点,第二个节点的r2放到新增节点,(一个primaryshard不能与他的从放到一
个节点)

节点扩展瓶颈
索引一共分3个shard ,我们就放3个节点,每个主节点 都放到不同的节点上,这时候我们想再加人2节点提高性能,我们新增的节点放
replicashard,primarshard 分配后就不能变了。
 
当有6台节点3个primar 3个replica  这个情况时候最多能容忍1台服务器宕机
三台节点,3个primar shard,提升容错率 把replica=2,就一个又9个shard ,每个节点3个shard,每个节点都保证有3不同的shard
容忍2台服务宕机

容错过程
上个例子 当master节点挂了(p0,r1,r2),装填立刻变成red
马上master选举,新master将丢失的primaryshard 的replica变成primary ,状态变成yellow(replica没了,变成了primary了)
从起故障node,将缺失的副本copy一份到该node(使用以前的数据,同步一下宕机后的修改)状态变成green
集群状态
red  不是所有的primary shard 都是active
yellow  不是所有的shard 都是active
green 所有shard active

元数据
_index
_type   分表  有不同的feild
_id
不同类型的数据 放到不同的index里 如产品索引创建一个   物流数据放到一个  ,就是类似于分库
相同功能的数据放到一个index
三者加一起 唯一定位一个document

document id
手动指定 自动生成
什么时候手动指定  :一般从其他的系统数据导入es时候。
我们自己的系统就用es存储 这个时候就用自动生成
put /index/type/id{}
post /index/type{}
自动生成id长度20 url安全base64编码的 guid(分布式并行生成id不会导致冲突)----------------------------?-----------------------
https://blog.youkuaiyun.com/dukesword/article/details/7945157

_source 元数据 返回指定的fieild
get /index/type/_search?_source=feildname,filedname2
get /index/type/_search

    “query”:{
          "match_all":{}
     },
      "_source":["feildname","filedname2"] 


document 全量替换
和创建一样,如果存在就全量替换
put /index/type/1{ json}
post /index/type/1/_update{json} ,这个json不是直接全部替换,而是看之前的json若属性有则替换属性值,没有的新增属性
document 是不可变的  ,修改 增量和全量替换都是把原来标记为删除 新增一个document,当es中数据越来越多时候,标记为delete
的都删除掉,释放空间。

强制创建
put /index/type/1/_create{} 或者 put /index/type/1?op_type=create 有会报错


 es并发冲突
读取库存 用户下单  更新库存,多用户多线程更新库存导致库存错误
es 使用乐观锁(version)防治并发冲突
主从复制 也是基于version 当更新的数据所带版本号小于es存储数据版本号时候这个更新无效
并发修改一个值时候 修改数据所带版本号小于数据版本号时候 拿到es存储的值再进行修改

es 可以用自己的_vesrion 进行并发控制    (?version=1  版本号等于才能更新)------------------???????????
es 也可以用 external version(自己数据的版本号) ?version=1&version_type=external   版本号大于才能更


es   groovy 脚本
内部脚本
post /index/type/11/_update{
   "script":"ctx._source.num+=1"
}  
外部脚本 
我们在es的安装目录 config /scripte/新增一个脚本test-add.groovy加入内容
ctx._source.tags+=new_tag
post /index/type/11/_update
{
   "script":{
        “lang”:“groovy”
         "file":"test-add",
         "params":{
                “new_tag”:“tag1”
         }
    }
}
ctx.op 操作
用脚本删除文档
写一个脚本deletgv
ctx.op=ctx._source.num==count?'delete':'none'
post /index/type/11/_update
{
   "lang":"groovy",
   "script":{
        file:"deletgv",
        params:{
            count:0
       }
    }
}

upsert 文档没有了初始化操作  有更新
post /index/type/11/_update
{
   "script":"ctx._source.num+=1",
   "upsert":{
       "num":0.
      "tags":[]
   }
}


批量查询 mget 减少网络开销
get  /_mget{
   "docs":[
       { “_index”:“名”,
          “_type”:“名”,
          “_id”:1
        },
        { “_index”:“名”,
          “_type”:“名”,
          “_id”:2
        }
   ]
}
 一个index 不同type
get  /index/_mget{
   “docs”:[
          {
          “_type”:“名”,
          “_id”:1
           },
        {
          “_type”:“名”,
          “_id”:2
        }
     ]
}

一个index 一个type
get /index/type/_mget{
  "ids":[1,2]
}

bulk  同一个json不能换行  ,不同的json有一个换行
为甚么这个格式呢,直接用换行符切割 ,22组成一组,路由到相应的shard,不会有内存占用太大。
不用着样的格式,我们没换行,我们先把这个json转成数据一样的jsonarry,通过这个jsonarry把数据路由到shard上去。这样占用内存
很多,要多一倍。


一个失败是不影响其他的操作的
delete  create (强制创建_create) index(就是put,创建或全部的覆盖) update(partial update) 
post  /_bulk
{ "delete":{"_index":"name","_type":"ming","_id":1}}
{"create":{"_idnex":"ming","_type":"ming","_id":1}}
{"feild1":"dsfs","filed2":"dfsdsf"}
{"index":{"_index":"ming","_type":"ming"}}
{"feild1","idzidong"}
{"update":{"_index":"ming","_type":"ming","_id":1,"_retry_on_conflict":5}}
{"doc":{feidl:value}}

post /index/_bulk
post /index/index/_bulk
我们要反复尝试bulksize的大小,这些都加入内存,定不好的话影响性能2000-5000尝试 10m左右


document  routing
保存一个document 具体放到哪个shard上
hash(rotuteing)%number_of_primary_shard
routing 默认就是documentid,也可以手动指定routing值 put /index/type/1?routing=useid 保证每一类型的数据路由到同一个
shard上去
每个index建立   他的primary shard 不可更改,这样才知道具体路由没问题

任何一个node都知道哪个shard在哪个节点上。
当一个请来了 访问任何一个节点(这个节点就就可以叫做协调节点 coordinate note)
根据ducumentid算出具体在那个primary shard上,并路由到那个节点,进行操作(增删改只能路由到primary shard),操作完,把
数据发送到replicashard ,都完成后 返回操作结果给协调节点,并返回给客户端。
这有一个异步操作,可以指定没有同步到replica完就可以吧结果返回给协调节点,返回给客端
---------------?????????????????????????------------------------

consistency 我们在 put/dddfsd/dfdf/1 时候可以指定这个?consistency=one quorum all
one  document在primary shard 上是active 就可以执行操作
qurum  大部分的shard是active就可以执行(默认的)
all 所有的shard是ative就可以执行

quorum 不齐 es 就会等待 希望shard active 数量增加 ,时间到了 就timeout  我们也可以指定?timeout=10s


primary shard 与replicashard 不能放一起
同一个的primary shard 的replica 不能放一起


document查询请求 内部流程,与增删改差不多,路由的时候可以路由到replica(随机轮询),当我路由到一个replica shard,但是这
个shard 还内有同布docuemnt ,这个时候提示找不到,当同步完成后,可以查询了。

默认是没有timeout的,正常es 会吧所有的结果搜索完成返回回来,当指定timeout时候,我们就设定的时间把查询到的结果返回回来。

multi-index  multi-type
get /index1,index2/
也可用通配符* 


分页 
put /index/type/_search?from=0&size=3
put /index/type/_search?from=3&size=3
深度分页 deep paging
3000条数据,3个shard ,每个shard1万,每页10条,搜索5000-5009,每个shard都要返回搜索5000-500910条数据,到一个节点上
汇总,拿出排序的10条,真的是这样吗?不是的
请求到协调节点上,把请求route在相应的shard,每个shard将内部的数据0-5009这些数据,每个shard都会吧这些收据传给协调节点,
协调节点排序,取自己需要的页数数据。
搜锁太深的时候在协调节点保存大量数据,还要排序,性能不好。


mapping
我们put 创建数据时候,会有一个dynamic mapping,自动为我们建立index,创建type 已经type对应的mapping,mapping包含每
个feild对应的数据类型(可能是 full text  extatc value),如何分词等设置。也可以手动创建index type mapping 在创建数据时。

get /index/_mapping/type

es 2种模式的搜索
exact value  值完全一样  必须输入2017-01-10 这样才能搜索出来 2017-01-10的数据
full text       输入01 就能把2017-01-10这样的数据查询出来
(缩写、格式转化 大小写 同义词)这些可以根据fulltext查询出来,指定不同的分词器就行


分词器
功能1.分词 2normaliation
组成部分
character filter 进行预处理  如把《span》hello《span》 转成hello   1&2 ->1 and 2
tokenizer 分词
token filter  单复数转换 同义词转换  大小写转换等
es 内置分词器
standard analyzer  
simple  analyzer  
whitespace  analyzer  
language analyzer  

查询时候 先会分词,我们使用什么分词器呢,es会使用对应的feild建立倒排索引时候所用的分词器

不同类型的feild 有的查询就是fulltext 有的局势extact vlaue
date 就是 extatc value
_all  shi full text
get /index/type/_search?q=post_date:2017
date类型是extact value 的 ,为什么这个记录会查出一条信息呢?——————————?????————————————————

mapping 数据类型
string byte short integer  long float double boolean  date
es 根据值推测类型
数字-》long  yyyy-dd -》date 小数-》double

手动建立mapping 只能新增一个feild mapping 不能修改

put  /indexname
{
 "mappings":{
      "typename":{
           "properties":{
                "filename":{
                     "type":"typename"
                  },
                "filename":{
                     "type":"typename",
                      “analyizer”:
                  },
                  "filename":{
                     "type":"typename"
                     “index”:“not_analyzers”
                  }
             }            
       }
  }
}
不让分词    “index”:“not_analyzers”  “index”:“analyzers” 分词  “index”:“no” 不让检索
 type keywords  表示不会分词
不能修改 只能给type 加feild
put /index/_mapping/type{
  "properties":{
       “feildname”:{
                。。。。。
         }
  }
}

put /index/_analyzer
{
  "feild":“filename”,
 “text”:“地方水电费第三方”
}

bool  组合多个条件
 must[]  必须匹配
should[]   相当于or
must_not [] 必须不匹配
minimum_should_match:1 最小匹配为1------------------------------------???------------------------------------------


filter query对比
filter只是过滤数据,对相关度 没有任何影响,query每个document会去算相应的相关度,并按大到小排序。 
filter不计算相关度 ,不排序,有内置的cache效率很高。

如何只用filter  constant_score
get /_search{
"query":{
    "constant_srcore":{
        “filter”:{
              “range”:{
                      "age":{
                            "gte":30
                       }
                  }
          }
   }
 }
}


multi_match:{
      “query”:“fssdsfs”,
         feilds:["feild1",feild2]

range 
get /_search{
     "query":{
          "range":{
               "age":{
                     "gte":20,"lt":30
                 }
           }
      }
}

term 把值当成extact value 去查 match 会去分词查询
get /_search{
 query:{
   "term ":{
      "filedname":"a b"
    }
 }

terms
get /_search{
 query:{
   "terms ":{
      "filedname":["a b","b c"," c d"]
    }
 }
a b ,b c ,c d 都不分词


判断你的搜索合不合法
get /index/type/_validate/query?explain
{body}

对string 字符串排序 往往是不准的,因为string 已经被分词了,排序时候可能不是按照原来的string排序了,吧这个sting索引两次
一个用来分词 一个用来排序

put /index
{
  "mappings":{
      "typename":{
           "properties":{
                "title":{
                     type:string,
                     ananlyzer:english ,
                      "feilds":{
                          "raw":{
                              "type":"string”,
                               index:"not_analyzed"
                           }
                       },
                      feilddate:ture   //正排索引-----------------------------------------------?????????????-----------------
                 }
           }
       }
  }
}

之后用title.raw 去sort


TF/IDF
相关度评分
1.搜索文本中的各个词条在feild出现都少次 ,出现的高  ,相关度高
比如 hello word
doc1:hello yu  word is good
doc2: word isbad 
hello 在doc1出现1次 doc2 0,word doc1 doc2 都出现1次,doc1 相关度高
2.搜索文本中的各个词条在整个索引的所有文档中出现的次数,次数越多,相关就越di
比如 比如 hello word
hellow 所有文档出现10000次,word所有文档出100次,
doc1:hello yu  is good
doc2: word isbad 
doc2的相关度就高于doc1
3filed 长度越长 相关度月小
如hellow word 
doc1:有一个短小的filed 包含hello
doc2 有一个长度大的feidl 包含word
1.2都一样的话,那么3的相关度doc1高,出现在小的filed里。

在查询的时候_serach?explain就能知道评分是如何算出来的

搜索的时候用倒排索引  排序时候用正排索引(聚合等都用的正派索引)
正排索引 就是 doc values
doc1: {name :song,age:20}
doc1: {name :song1,age:21}
建立的正排索引就是
document   name    age
doc1            song    20
doc2            song1  21
排序按age拍就直接sortage大小就ok了,
创建索引时候 正派倒排都建立好了


query phase
来一个请求,请求的协调节点将建立一个priority queue ,大小有请求的 from size决定,form为1000,size=10 大小为1010,
之后吧请求route到各个shard,每个shard同样创建这么个 priority queue,并把结果放到queue中,把queue返回给协调节点,此时
获取的是一些docid,这个时候mget去各个shard批量获取(若用_souce查询,那么可以直接把document返回)
协调节点吧所有的进行merger,符合要求的放到自己的queue,
并返回给客户端。

没from size jiushi 前10条

跳跃结果
因为给个shard 的存放数据可能排序不同,请求结果可能来自不同的shard,这样可能导致查询结果排序不同。解决方案是设置
preference为字符串,让每次查询都去制定的shard去搜索。

scoll 技术搜索大量数据
一次查询很大两数据性能会很慢,我们使用scoll技术,一批一批的查询,直到所有的数据处理完。
使用scoll数据会在第一次执行时候,建立一个视图快照,之后就基于这个视图快zhao提供数据搜索。
get /index/type/_search?scoll=1m
{
  "query":{
     “match_all”:{}
  },
  "sort":["_doc"],
  "size":3
}
这批查询 返回3个结果集,返回一个scollid,
如何下一批查询呢
get  /_search/scoll
{
   scoll=1m,
  "scoll_id":"shangmianfanhui de scollid"
}


创建索引
put /my_index
{
    "setting":{
        "number_of_shards":1,
        "number_of_replicas":0
     },
     "mapping":{
        "my_type":{
             "my_feild":{
                  "type":"string"
              }
          }
    }
}

修改索引
number_of_shard bu neng 修改 ,mapping 只能新增feild 不能修改feild

delete /my_index

定制自己的分词器


doc1:name  age  school  sex
doc2:name  age  school  birthday
子lunce底层是

    ecommerce:{
       mapping:{
          _type:"string",
         idnex:not
      },
    "name":{
       type:string
      },
   "age":{
       type:string
      },
  "school":{
       type:string
      },
  "sex":{
       type:string
      },
  "birthday":{
       type:string
      }
   }


他把所有的type都存在一起。
最佳实践 把类似的type放到一个index 下 ,这些type 应该是有多个相同的feild
如把完全不同的type放到一个index下 在lunce中会有一半的field是空,严重的浪费空间,影响性能。
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值