hi,你好!欢迎访问本站!登录
本站由网站地图腾讯云宝塔系统阿里云强势驱动
当前位置:首页 - 教程 - 杂谈 - 正文 君子好学,自强不息!

干货 Elasticsearch 知识点整顿 一

2019-11-18杂谈搜奇网37°c
A+ A-

极力引荐: 官网地点: https://www.elastic.co/guide/en/elasticsearch/reference/6.0

肺腑之言,学ES先学原生的语法,SpringData封装的是太好用了,然则没玩过原生的语法,能够不知道Spring供应的API在干什么

中心观点:

Near Realtime (NRT)

在ES中举行搜刮是近及时的,意义是数据从写入ES到能够被searchable仅仅须要1秒钟,因而说基于ES实行的搜刮和剖析能够到达秒级

Cluster

集群 , 集群是一个或多个node的鸠合,他们一同保留你寄存进去的数据,用户能够在一切的node之间举行检索,平常的每一个集群都邑有一个唯一的称号标识,默许的称号标识为 elasticsearch , 这个名字很主要,由于node想到场cluster时,须要这个称号信息

确保别在差别的环境中运用雷同的集群称号,进而防止node加错集群的状况,一颗斟酌下面的集群定名作风logging-stagelogging-devlogging-pro

Node

单台server就是一个node,他和 cluster一样,也存在一个默许的称号,然则它的称号是经由过程UUID生成的随机串,固然用户也能够定制差别的称号,然则这个名字最好别反复,这个称号关于治理来讲很在意要,由于须要肯定,当前收集中的哪台服务器,对应这个集群中的哪一个节点

node存在一个默许的设置,默许的,当每一个node在启动时都邑自动的去到场一个叫elasticsearch的节点,这就意味着,假如用户在收集中启动了多个node,他们会相互发明,然后构成集群

在单个的cluster中,你能够具有恣意多的node,假如说你的收集上没有有其他正在运转的节点,然后你启动一个新的节点,这个新的节点本身会组件一个集群

Index

Index是一类具有相似属性的document的鸠合,比方你能够为消费者的数据建立一个index,为产物建立一个index,为定单建立一个index

index称号(必需是小写的字符), 当须要对index中的文档实行索引,搜刮,更新,删除,等操纵时,都须要用到这个index

一个集群中理论上你能够建立恣意数目的index

Type

Type能够作为index中的逻辑种别,为了更细的分别,比方用户数据type,批评数据type,博客数据type

在设计时,尽最大努力让具有更多雷同field的document会分为同一个type下

Document

document就是ES中存储的一条数据,就像mysql中的一行纪录一样,能够是一条用户的纪录,一个商品的纪录等等

一个不严谨的小结:

为何说这是不严谨的小结呢? 就是说下面三个对应关联只能说的从表面上看起来比较相似,然则ES中的type实际上是一个逻辑上的分别,数据在存储是时刻依旧是混在一同存储的(往下看下文中有写,),但是mysql中的差别表的两个列是相对没有关联的

Elasticsearch 关联型数据库
Document
type
index 数据库

Shards & Replicas

题目引入:

假如让一个Index本身存储1TB的数据,相应的速率就会下落为了处置惩罚这个题目,ES供应了一种将用户的Index举行subdivide的骚操纵,就是将index分片, 每一片都叫一个Shards,完成了将团体巨大的数据散布在差别的服务器上存储

什么是shard?

shard分红replica shard和primary shard,望文生义一个是主shard一个是备份shard, 担任容错以及负担部份读请求

shard能够明白成是ES中最小的事情单位,一切shard中的数据之和,才是悉数ES中存储的数据, 能够把shard明白成是一个luncene的完成,具有完成的建立索引,处置惩罚请求的才能

下图是两个node,6个shard的构成的集群的分别状况

人人能够看到,这时候不论java应用程序接见的是node1照样node2,实在都能猎取到数据

shard的默许数目

新建立的节点会存在5个primary shard,后续不然能再修正primary shard的值,假如每一个primary shard都对应一个replica shard,按理说单台es启动就会存在10个分片,然则现实是,同一个节点的replica shard和primary shard不能存在于一个server中,因而单台es默许启动后的分片数目照样5个

怎样拓容Cluster

起首明白一点: 一旦index建立完成了,primary shard的数目就不能够再发作变化

因而横向拓展就得增添replica的数目, 由于replica shard的数目后续是能够修正的, 也就是说,假如后续我们将他的数目改成了2, 就意味着让每一个primary shard都具有了两个replica shard, 盘算一下: 5+5*2=15 集群就会拓展成15个节点

假如想让每一个shard都有最多的体系的资本,就增添服务器的数目,让每一个shard独有一个服务器,

举个例子:

上图中存在高低两个node,每一个node,每一个node中都有一个 本身的primary shard其他节点的replica shard,为何是强调本身和其他呢? 由于ES中划定,同一个节点的replica shard和primary shard不能存在于一个server中,然则差别节点的primary shard能够存在于同一个server上

当primary shard宕机时,它对应的replicas在其他的server不会受到影响,能够继承相应用户的读请求,经由过程这类分片的机制,而且分片的职位相称,假定单个shard能够处置惩罚2000/s的请求,经由过程横向拓展能够在此基础上成倍提拔体系的吞吐量,天生散布式,高可用

另外:每一个document肯定存在于一个primary shard和这个primary shard 对应的replica shard中, 相对不会涌现同一个document同时存在于多个primary shard中的状况

入门探究:

集群的健康状况

GET /_cat/health?v

实行效果以下:

epoch      timestamp cluster       status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1572595632 16:07:12  elasticsearch yellow          1         1      5   5    0    0        5             0                  -                 50.0%

解读上面的信息,默许的集群名是elasticsearch,当前集群的status是yellow,后续列出来的是集群的分片信息,末了一个active_shards_percent示意当前集群中唯逐一半shard是可用的

状况

存在三种状况分别是red green yellow

  • green : 示意当前集群一切的节点悉数可用
  • yellow: 示意一切的数据是能够接见的,然则并非一切的replica shard都是能够运用的(我如今是默许启动一个node,而ES又不许可同一个node的primary shard和replica shard共存,因而我当前的node中仅仅存在5个primary shard,为status为黄色)
  • red: 集群宕机,数据不可接见

集群的索引信息

GET /_cat/indices?v

效果:

health status index              uuid                   pri rep docs.count docs.deleted store.size pri.store.size
yellow open   ai_answer_question cl_oJNRPRV-bdBBBLLL05g   5   1     203459            0    172.3mb        172.3mb

显现,状况yellow示意存在replica shard不可用, 存在5个primary shard,而且每一个primary shard都有一个replica shard , 一共20多万条文档,未删除过文档,文档占用的空间状况为172.3兆

建立index

PUT /customer?pretty

ES 运用的RestfulAPI,新增运用put,这是个很亲民的行为

增添 or 修正

假如是ES中没有过下面的数据则增添进去,假如存在了id=1的元素就修正(全量替代)

  • 花样:PUT /index/type/id

全量替代时,本来的document是没有被删除的,而是被标记为deleted,被标记成的deleted是不会被检索出来的,当ES中数据愈来愈多时,才会删除它

PUT /customer/_doc/1?pretty
{
  "name": "John Doe"
}

相应:

{
  "_index": "customer",
  "_type": "_doc",
  "_id": "1",
  "_version": 1,
  "result": "created",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 0,
  "_primary_term": 1
}

强迫建立,加添_create或许?op_type=create

PUT /customer/_doc/1?op_type=create
PUT /customer/_doc/1/_create
  • 部分更新(Partial Update)

不指定id则新增document

POST /customer/_doc?pretty
{
  "name": "Jane Doe"
}

指定id则举行doc的部分更新操纵

POST /customer/_doc/1?pretty
{
  "name": "Jane Doe"
}

而且POST相干于上面的PUT而言,不论是不是存在雷同内容的doc,只需不指定id,都邑运用一个随机的串当做id,完成doc的插进去

Partial Update先猎取document,再将通报过来的field更新进document的json中,将老的doc标记为deleted,再将建立document,相干于全量替代中心会省去两次收集请求

检索

花样: GET /index/type/

GET /customer/_doc/1?pretty

相应:

{
  "_index": "customer",
  "_type": "_doc",
  "_id": "1",
  "_version": 1,
  "found": true,
  "_source": {
    "name": "John Doe"
  }
}

删除

删除一条document

大部份状况下,本来的document不会被马上删除,而是被标记为deleted,被标记成的deleted是不会被检索出来的,当ES中数据愈来愈多时,才会删除它

DELETE /customer/_doc/1

相应:

{
  "_index": "customer",
  "_type": "_doc",
  "_id": "1",
  "_version": 2,
  "result": "deleted",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 1,
  "_primary_term": 1
}

删除index

DELETE /index1
DELETE /index1,index2
DELETE /index*
DELETE /_all

能够在elasticsearch.yml中将下面这个设置置为ture,示意制止运用 DELETE /_all
action.destructive_required_name:true

相应

{
  "acknowledged": true
}

更新文档

上面说了POST关键字,能够完成不指定id就完成document的插进去, POST + _update关键字能够完成更新的操纵

POST /customer/_doc/1/_update?pretty
{
  "doc": { "name": "changwu" }
}

**POST+_update举行更新的行动依旧须要实行id, 然则它相干于PUT来讲,当运用POST举行更新时,id不存在的话会报错,而PUT则会以为这是在新增**

另外: 针对这类更新操纵,ES会先删除本来的doc,然后插进去这个新的doc

document api

multi-index & multi-type

  • 检索一切索引下面的一切数据
/_search
  • 搜刮指定索引下的一切数据
/index/_search
  • 更多情势
/index1/index2/_search
/*1/*2/_search
/index1/index2/type1/type2/_search
/_all/type1/type2/_search

_mget api 批量查询

  • 在docs中指定_index,_type,_id
GET /_mget
{
    "docs" : [
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "1"
        },
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "2"
        }
    ]
}
  • 在URL中指定index
GET /test/_mget
{
    "docs" : [
        {
            "_type" : "_doc",
            "_id" : "1"
        },
        {
            "_type" : "_doc",
            "_id" : "2"
        }
    ]
}
  • 在URL中指定 index和type
GET /test/type/_mget
{
    "docs" : [
        {
            "_id" : "1"
        },
        {
            "_id" : "2"
        }
  • 在URL中指定index和type,并运用ids指定id局限
GET /test/type/_mget
{
    "ids" : ["1", "2"]
}
  • 为差别的doc指定差别的过滤划定规矩
GET /_mget
{
    "docs" : [
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "1",
            "_source" : false
        },
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "2",
            "_source" : ["field3", "field4"]
        },
        {
            "_index" : "test",
            "_type" : "_doc",
            "_id" : "3",
            "_source" : {
                "include": ["user"],
                "exclude": ["user.location"]
            }
        }
    ]
}

_bulk api 批量增编削

基础语法

{"action":{"metadata"}}\n
{"data"}\n

存在哪些范例的操纵能够实行呢?

  • delete: 删除文档

  • create: _create 强迫建立

  • index: 示意一般的put操纵,能够是建立文档也能够是全量替代文档

  • update: 部分替代

上面的语法中并非人们习气浏览的json花样,然则这类单行情势的json更具有高效的上风

ES怎样处置惩罚一般的json以下:

  • 将json数组转换为JSONArray对象,这就意味着内存中会涌现一份如出一辙的拷贝,一份是json文本,一份是JSONArray对象

然则假如上面的单行JSON,ES直接举行切割运用,不会在内存中整一个数据拷贝出来

delete

delete比较悦目仅仅须要一行json就ok

{ "delete" : { "_index" : "test", "_type" : "_doc", "_id" : "2" } }

create

两行json,第一行指明我们要建立的json的index,type以及id

第二行指明我们要建立的doc的数据

{ "create" : { "_index" : "test", "_type" : "_doc", "_id" : "3" } }
{ "field1" : "value3" }

index

相称因而PUT,能够完成新建或许是全量替代,一样是两行json

第一行示意将要新建或许是全量替代的json的index type 以及 id

第二行是详细的数据

{ "index" : { "_index" : "test", "_type" : "_doc", "_id" : "1" } }
{ "field1" : "value1" }

update

示意 parcial update,部分替代

他能够指定一个retry_on_conflict的特征,示意能够重试3次

POST _bulk
{ "update" : {"_id" : "1", "_type" : "_doc", "_index" : "index1", "retry_on_conflict" : 3} }
{ "doc" : {"field" : "value"} }
{ "update" : { "_id" : "0", "_type" : "_doc", "_index" : "index1", "retry_on_conflict" : 3} }
{ "script" : { "source": "ctx._source.counter += params.param1", "lang" : "painless", "params" : {"param1" : 1}}, "upsert" : {"counter" : 1}}
{ "update" : {"_id" : "2", "_type" : "_doc", "_index" : "index1", "retry_on_conflict" : 3} }
{ "doc" : {"field" : "value"}, "doc_as_upsert" : true }
{ "update" : {"_id" : "3", "_type" : "_doc", "_index" : "index1", "_source" : true} }
{ "doc" : {"field" : "value"} }
{ "update" : {"_id" : "4", "_type" : "_doc", "_index" : "index1"} }
{ "doc" : {"field" : "value"}, "_source": true}

转动查询手艺

转动查询手艺和分页手艺在运用场景方面照样存在相差的,这里的转动查询手艺一样适用于体系在海量数据中举行检索,比方过一次性存在10条数据被掷中能够被检索出来,那末机能肯定会很差,这时候能够挑选运用转动查询手艺,一批一批的查询,直到一切的数据被查询完成他能够先搜刮一批数据再搜刮一批数据

采纳基于_doc的排序体式格局会取得较高的机能

每次发送scroll请求,我们还须要指定一个scroll参数,指定一个时候窗口,每次搜刮只需在这个时候窗口内完造诣ok

示例

GET /index/type/_search?scroll=1m
{
    "query":{
        "match_all":{}
    },
    "sort":["_doc"],
    "size":3
}

相应

{
  "_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAACNFlJmWHZLTkFhU0plbzlHX01LU2VzUXcAAAAAAAAAkRZSZlh2S05BYVNKZW85R19NS1Nlc1F3AAAAAAAAAI8WUmZYdktOQWFTSmVvOUdfTUtTZXNRdwAAAAAAAACQFlJmWHZLTkFhU0plbzlHX01LU2VzUXcAAAAAAAAAjhZSZlh2S05BYVNKZW85R19NS1Nlc1F3",
  "took": 9,
  "timed_out": false,
  "_shards": {
    "total": 5,
    "successful": 5,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "total": 2,
    "max_score": null,
    "hits": [
      {
        "_index": "my_index",
        "_type": "_doc",
        "_id": "2",
        "_score": null,
        "_source": {
          "title": "This is another document",
          "body": "This document has a body"
        },
        "sort": [
          0
        ]
      },
      {
        "_index": "my_index",
        "_type": "_doc",
        "_id": "1",
        "_score": null,
        "_source": {
          "title": "This is a document"
        },
        "sort": [
          0
        ]
      }
    ]
  }
}

再次转动查询

GET /_search/scroll
{
    "scroll":"1m",
    "_scroll_id": "DnF1ZXJ5VGhlbkZldGNoBQAAAAAAAACNFlJmWHZLTkFhU0plbzlHX01LU2VzUXcAAAAAAAAAkRZSZlh2S05BYVNKZW85R19NS1Nlc1F3AAAAAAAAAI8WUmZYdktOQWFTSmVvOUdfTUtTZXNRdwAAAAAAAACQFlJmWHZLTkFhU0plbzlHX01LU2VzUXcAAAAAAAAAjhZSZlh2S05BYVNKZW85R19NS1Nlc1F3"
}

_search api 搜刮api

query string search

_searchAPI + 将请求写在URI中

GET /bank/_search?q=*&sort=account_number:asc&pretty

一样运用的是RestfulAPI, q=* ,示意婚配index=bank的下的一切doc,sort=account_number:asc示意通知ES,效果依据account_number字段升序排序,pretty是通知ES,返回一个美丽的json花样的数据

上面的q还能够写成下面如许

GET /bank/_search?q=自定义field:希冀的值
GET /bank/_search?q=+自定义field:希冀的值
GET /bank/_search?q=-自定义field:希冀的值

相应:

{
  "took" : 63,    // 消耗的时候
  "timed_out" : false,  // 是不是超时了
  "_shards" : {   // 分片信息
    "total" : 5, // 统共5个分片,它的搜刮请求会被打到5个分片上去,而且都胜利了
    "successful" : 5,  // 
    "skipped" : 0, // 跳过了0个
    "failed" : 0 // 失利了0个
  },
  "hits" : {  //掷中的状况
    "total" : 1000,  // 掷中率 1000个
    "max_score" : null,  // 相干性得分,越相干就越婚配
    "hits" : [ {   
      "_index" : "bank",  // 索引
      "_type" : "_doc",   // type
      "_id" : "0",  // id 
      "sort": [0], 
      "_score" : null, // 相干性得分
                    // _source内里寄存的是数据
      "_source" : {"account_number":0,"balance":16623,"firstname":"Bradshaw","lastname":"Mckenzie","age":29,"gender":"F","address":"244 Columbus Place","employer":"Euron","email":"bradshawmckenzie@euron.com","city":"Hobucken","state":"CO"}
    }, {
      "_index" : "bank",
      "_type" : "_doc",
      "_id" : "1",
      "sort": [1],
      "_score" : null,
      "_source" : {"account_number":1,"balance":39225,"firstname":"Amber","lastname":"Duke","age":32,"gender":"M","address":"880 Holmes Lane","employer":"Pyrami","email":"amberduke@pyrami.com","city":"Brogan","state":"IL"}
    }, ...
    ]
  }
}

指定超时时候: GET /_search?timeout=10ms 在举行优化时,能够斟酌运用timeout, 比方: 一般来讲我们能够在10s内猎取2000条数据,然则指定了timeout,发作超时后我们能够猎取10ms中猎取到的 100条数据

query dsl (domain specified language)

下面我仅仅列出来了一点点, 更多的示例,拜见官网 点击进入官网

_searchAPI +将请求写在请求体中

GET /bank/_search
{
  "query": { "match_all": {} }, # 查询悉数
  "query": { "match": {"name":"changwu zhu"} }, # 全文检索,户将输入的字符串拆解开,去倒排索引中逐一婚配, 哪怕婚配上了一个也会将效果返回
  # 实际上,上面的操纵会被ES转换成下面的花样
  #
  # {
  #    "bool":{
  #        "should":[
  #         {"term":{"title":"changwu"}},
  #         {"term":{"title":"zhu"}}
  #     ]
  #  }
  # }
  #
   "query": { 
     "match": { # 手动掌握全文检索的精度,
        "name":{
            "query":"changwu zhu",
            "operator":"and",  # and示意,只要同时涌现changwu zhu 两个词的doc才会被掷中
            "minimum_should_match":"75%" # 去长尾,掌握最少掷中3/4才算是真正掷中
        }
     }
    }, # 全文检索,operator 示意
  # 增添上operator 操纵会被ES转换成下面的花样,将上面的should转换成must
  #
  # {
  #    "bool":{
  #        "must":[
  #         {"term":{"title":"changwu"}},
  #         {"term":{"title":"zhu"}}
  #     ]
  #  }
  # }
  #
  # 增添上 minimum_should_match 操纵会被ES转换成下面的花样 
  #
  # {
  #    "bool":{
  #        "should":[
  #         {"term":{"title":"changwu"}},
  #         {"term":{"title":"zhu"}}
  #     ],
  #       "minimum_should_match":3
  #  }
  # }
  #  
   "query": { 
     "match": { #掌握权重, 
        "name":{
            "query":"changwu zhu",
            "boost":3  # 将name字段的权重提拔成3,默许状况下,一切字段的权重都是样的,都是1
        }
     }
    },
   "query": { 
   # 这类用法不容疏忽
     "dis_max": { # 直接取下面多个query中得分最高的query当做终究得分
        "queries":[
           {"match":{"name":"changwu zhu"}},
           {"match":{"content":"changwu"}}
        ]
     }
    },
    
    # best field战略
    "query": { # 基于 tie_breaker 优化dis_max
    # tie_breaker能够使dis_max斟酌其他field的得分影响
       "multi_match":{
           "query":"用于去婚配的字段",
           "type":"most_fields",# 指定检索的战略most_fields
           "fields":["field1","field2","field3"]
       }
    },
    
    # most field 战略, 优先返回掷中更多关键词的doc, (疏忽从哪一个,从多少个field中掷中的,只需掷中就行)
    "query": { # 基于 tie_breaker 优化dis_max
    # tie_breaker能够使dis_max斟酌其他field的得分影响
     "dis_max": { # 直接取下面多个query中得分最高的query当做终究得分, 这也是best field战略
        "queries":[
           {"match":{"name":"changwu zhu"}},
           {"match":{"content":"changwu"}}
        ],
        "tie_breaker":0.4
     }
    },
    
    
  "query": { "match_none": {} }
  "query": { "term": {"test_field":"指定值"} } # 准确婚配
  "query": { "exits": {"field":"title"} } # title不为空(然则这时候ES2.0中的用法,如今不再供应了)
  "query": {  # 短语检索 
              # 递次的保证是经由过程 term position来保证的
              # 精准度很高,然则召回率低
         "match_phrase": { # 只要address字段中包括了完全的 mill lane (相连,递次也不能变) 时,这个doc才算掷中
             "address": "mill lane"
             } 
  },
   "query": {  # 短语检索 
         "match_phrase": { 
             "address": "mill lane",
             # 指定了slop就不再请求搜刮term之间必需相邻,而是能够最多间隔slop间隔
             # 在指定了slop参数的状况下,离关键词越近,挪动的次数越少, relevance score 越高
             # match_phrase +  slop 和 proximity match 近似婚配作用相似
             # 均衡精准度和召回率
             "slop":1 # 指定搜刮文本中的几个term经由频频挪动后能够婚配到一个doc
             } 
  },
  
  # 夹杂运用match和match_phrase 均衡精准度和召回率
   "query": { 
      "bool": {  
      "must":  {
          # 全文检索虽然能够婚配到大批的文档,然则它不能掌握词条之间的间隔
          # 能够java elasticsearch在Adoc中间隔很近,然则它却被ES排在效果集的背面
          # 它的机能比match_phrase高10倍,比proximity高20倍
         "match": {
            "address": "java elasticsearch" 
            } 
      },
      "should": {
         # 借助match_phrase+slop能够感知term position的功用,为间隔邻近的doc孝敬分数,让它们靠前分列
          "match_phrase":{
              "title":{
                  "query":"java elasticsearch",
                  "slop":50
              }
          }
      }
  },
  
  # 重打分机制
   "query": { 
       "match":{
           "title":{
               "query":"java elasticsearch",
               "minimum_should_match":"50%"
           }
       },
       "rescore":{ # 对全文检索的效果举行从新打分
           "window_size":50,  # 对全文检索的前50条举行从新打分
           "query": { 
               "rescore_query":{ # 关键字
                    "match_phrase":{ # match_phrase + slop 感知 term persition,孝敬分数
                       "title":{
                           "query":"java elasticsearch",
                           "slop":50
                  }
              }
          }
       }
   }
  
  # 前缀婚配, 相干于全文检索,前缀婚配是不会举行分词的,而且每次婚配都邑扫描悉数倒排索引,直到扫描完一遍才会停下来
  # 不会盘算相干性得分,前缀越短拼配到的越多,机能越不好
  "query": { # 查询多个, 鄙人面指定的两个字段中检索含有 `this is a test`的doc
    "multi_match" : {
      "query":    "this is a test", 
      "fields": [ "subject", "message" ] 
    }
  },
  "query": { # 前缀搜刮,搜刮 user字段以ki开首的 doc
    "prefix" : { "user" : "ki" }
  },
  "query": { # 前缀搜刮 + 增添权重
    "prefix" : { "user" :  { "value" : "ki", "boost" : 2.0 } }
  },
  
  # 通配符搜刮
   "query": {
        "wildcard" : { "user" : "ki*y" }
    },
   "query": {
        "wildcard" : { "user" : { "value" : "ki*y", "boost" : 2.0 } }
    }
  # 正则搜刮
   "query": {
        "regexp":{
            "name.first": "s.*y"
        }
    },
   "query": {# 正则搜刮
        "regexp":{
            "name.first":{
                "value":"s.*y",
                "boost":1.2
            }
        }
    },
  # 搜刮引荐, 相似于百度,当用户输入一个词条后,将其他相符前提的词条的选项推送出来
  # 道理和match_pharse相似,然则唯一的区分就是会将末了一个term看成前缀去搜刮
  # 下例中: 运用quick brown举行match 运用f举行前缀搜刮,运用slop调解term persition,孝敬得分
   "query": {
      "match_phrase_prefix" : {# 前缀婚配
        "message" : {
                "query" : "quick brown f",
                "max_expansions" : 10, # 指定前缀最多婚配多少个term,凌驾这个数目就不在倒排索引中检索了,提拔机能
                "slop":10
            }
       } 
  },
  # Function Score Query
  # 用户能够自定义一个function_secore 函数,然后将某个field的值和ES盘算出来的分数举行运算
  # 终究完成对本身指定的field举行分数的加强功用
  "query": {
        "function_score": {
            "query": { "match_all": {} },
            "boost": "5",
            "random_score": {}, 
            "boost_mode":"multiply"
        }
    }, 
  
  # Fuzzy Query 隐约查询会供应容错的处置惩罚
   "query": {
        "fuzzy" : {
            "user" : {
                "value": "ki",
                "boost": 1.0,
                "fuzziness": 2, # 做大的纠错数目
                "prefix_length": 0,# 不会被“隐约化”的初始字符数。这有助于削减必需搜检的术语的数目。默许值为0。
                "max_expansions": 100 # 隐约查询将扩展到的最大项数。默许值为50
                transpositions:true # 是不是支撑隐约变更(ab→ba)。默许的是假的
            }
        }
    }
  
  "query": {
    "bool": {  # 布尔查询, 终究经由过程将它内置must,should等查询的得分加起来/should,must的总数, 获得终究的得分
      "must": [ # 必需婚配到XXX, 而且会得出相干性得分
        { "match": { "address": "mill" } }, # address中必需包括mill
      ],
      # 在满足must的基础上,should前提不满足也能够,然则假如也婚配上了,相干性得分会增添
      # 假如没有must的话,should中的前提必需满足一个
      "should": [ # 指定能够包括的值, should是能够影响相干性得分的
        { "match": { "address": "lane" } }
      ],
      "must_not": [ # 肯定不包括谁
        { "match": { "address": "mill" } },
      ],
      "filter": { # 对数据举行过滤
        "range": { # 依据局限过滤
          "balance": { # 指定过滤的字段
            "gte": 20000, # 高于20000
            "lte": 30000  # 低于30000
          }
        }
      }
    }
  }

在上面的组合查询中,每一个子查询都邑盘算一下他的相干性分数,然后由最外层的bool综合兼并一个得分,然则 filter是不会盘算分数的

默许的排序划定规矩是依据score降序排序,但像上面说的那样,假如悉数都是filter的话他就不会盘算得分,也就是说一切的得分满是1,这时候刻就须要定制排序划定规矩,定义的语法我在上面写了

其他辅佐API

比方下面的高亮,排序,分页,以及_source 指定须要的字段都能够进一步作用在query的效果上

  "highlight":{ # 高亮显现
    "fields":{  # 指定高亮的字段
      "balance":{}
  },
  "sort": [  # 指定排序前提
    { "account_number": "asc" } # 依据账户余额降序
  ],
  "from": 0, # 分页
  "size": 10, # 每页的大小4,经由过程实行size=0,能够完成仅显现聚合效果而不显现掷中的信息概况
  "_source": ["account_number", "balance"], # 默许状况下,ES会返回全文JSON,经由过程_source能够指定返回的字段

聚合剖析

聚合剖析是基于doc value如许一个数据效果举行的,前面有说过,这个doc value 实在就是正排索引, 聚合剖析就是依据某一个字段举行分组,请求这个字段是不能被分词的,假如被聚合的字段被分词,依据倒排索引的体式格局去索引的话,就不得不去扫描悉数倒排索引(才能够将被聚合的字段找全,效力很低)

更多Aggregate 点击进入ES官网

三个观点:

  • 什么是bucket?

bucket就是聚合获得的效果

  • 什么是metric?

metric就是对bucket举行剖析,如最最大值,最小值,均匀值

  • 什么是下钻?

下钻就是在现有的分好组的bucket继承分组,比方一个先按性别分组,再按岁数分组

聚合的关键字: aggsquery职位并列

  
  # 运用聚应时,天然存在一个metric,就是当前bucket的count
  "aggs": { # 聚合
    "group_by_state": { # 自定义的名字
      "term": {
        "field": "balance" # 指定聚合的字段, 意义是 group by balance
      },
       "terms": { # terms
        "field": {"value1","value2","value3"} # 指定聚合的字段, 意义是 group by balance
      }
    }
  },    
  "aggs": { # 聚合中嵌套聚合
    "group_by_state": {
      "terms": {
        "field": "field1"
      },
      "aggs": { # 聚合中嵌套聚合
        "average_balance": {
          "avg": {
            "field": "field2"
          }
        }
      }
    }
  },
   "aggs": { #嵌套聚合,而且运用内部聚合的效果集
    "group_by_state": {
      "terms": {
        "field": "state.keyword",
        "order": {
          "average_balance": "desc" # 运用的下面聚合的效果集
        }
      },
      "aggs": {
        "average_balance": {
          "avg": {  # avg 求均匀值  metric
            "field": "balance"
          }
        },
         "min_price": {
          "min": {  # metric 求最小值
            "field": "price"
          }
        },
         "max_price": {
          "max": {  # metric 求最大值
            "field": "price"
          }
        },
         "sum_price": {
          "sum": {  #  metric 盘算总和
            "field": "price"
          }
        },
      }
    }
  },
   "aggs": { # 先依据岁数分组,在依据性别分组,再依据均匀工资聚合
             # 终究的效果就获得了每一个岁数段,每一个性别的均匀账户余额
    "group_by_age": {
      "range": {
        "field": "age",
        "ranges": [
          {
            "from": 20,
            "to": 30
          }
        ]
      },
      "aggs": {
        "group_by_gender": {
          "terms": {
            "field": "gender.keyword"
          },
          "aggs": {
            "average_balance": {
              "avg": {
                "field": "balance"
              }
            }
          }
        }
      },
      # histogram,相似于terms, 一样会举行bucket分组操纵,接收一个field,依据这个field的值的各个局限区间举行分组操纵
      # 比方我们指定为2000, 它会分别成如许 0-2000  2000-4000  4000-6000 ...
      "aggs": { # 聚合中嵌套聚合  
         "group_by_price": {
              "histogram": {
                 "field": "price",
                 "interval":2000
             },
         "aggs": { # 聚合中嵌套聚合
             "average_price": {
               "avg": {
                  "field": "price"
               }
           }
        }
    }
  },
  "aggs" : {
        "sales_over_time" : { # 依据日期举行聚合
            "date_histogram" : {
                "field" : "date",
                "interval" : "1M",# 一个月为一个跨度
                "format" : "yyyy-MM-dd",
                "min_doc_count":0 #纵然这个区间中一条数据都没有,这个区间也要返回
            } 
        }
    }
    }
  }
}

filter aggregate

过滤加聚合,统计type=t-shirt的均匀价钱

POST /sales/_search?size=0
{
    "aggs" : {
        "t_shirts" : {
            "filter" : { "term": { "type": "t-shirt" } },
            "aggs" : {
                "avg_price" : { "avg" : { "field" : "price" } }
            }
        }
    }
}

嵌套聚合-广度优先

说一个应用于场景: 我们检索影戏的批评, 然则我们先依据演员分组聚合,在依据批评的数目举行聚合

剖析: 假如我们挑选深度优先的话, ES在构建演员影戏相干信息时,会顺路盘算出影戏下面批评数的信息,假如说有10万个演员的话, 10万*10=100万个影戏 每一个影戏下又有许多影评,接着处置惩罚影评, 就如许内存中能够会存在几百万条数据,然则我们终究就须要50条,这类开支是很大的

广度优先的话,是我们先处置惩罚影戏数,而不论影戏的批评数的聚合状况,先从10万演员中干掉99990条数据,剩下10个演员再聚合

        "aggs":{
            "target_actors":{
                "terms":{
                    "field":"actors",
                    "size":10,
                    "collect_mode":"breadth_first" # 广度优先
                }
            }
        }

global aggregation

全局聚合,下面先运用query举行全文检索,然后举行聚合, 下面的聚合实际上是针对两个差别的效果举行聚合,第一个聚合增添了global关键字,意义是ES中存在的一切doc举行聚合盘算得出t-shirt的均匀价钱

第二个聚合针对全文检索的效果举行聚合

POST /sales/_search?size=0
{
    "query" : {
        "match" : { "type" : "t-shirt" }
    },
    "aggs" : {
        "all_products" : {
            "global" : {}, 
            "aggs" : { 
                "avg_price" : { "avg" : { "field" : "price" } }
            }
        },
        "t_shirts": { "avg" : { "field" : "price" } }
    }
}

Cardinality Aggregate 基数聚合

作用相似于count(distcint),会对每一个bucket中指定的field举行去重,然后取去重后的count

虽然她会存在5%摆布的错误率,然则机能迥殊好

POST /sales/_search?size=0
{
    "aggs" : {
        "type_count" : {
            "cardinality" : { # 关键字
                "field" : "type"
            }
        }
    }
}

对Cardinality Aggregate的机能优化, 增添 precision_threshold 优化准确率和内存的开支

下面的示例中将precision_threshold的值调解到100意义是当 type的范例小于100时,去重的精准度为100%, 此时内存的占用状况为 100*8=800字节

到场我们将这个值调解为1000,意义是当type的品种在1000个之内时,去重的精准度100%,内存的占用率为1000*8=80KB

官方给出的目标是, 当将precision_threshold设置为5时,错误率会被掌握在5%之内

POST /sales/_search?size=0
{
    "aggs" : {
        "type_count" : {
            "cardinality" : { # 关键字
                "field" : "type",
                "precision_threshold":100
            }
        }
    }
}

进一步优化,Cardinality底层运用的算法是 HyperLogLog++, 能够针对这个算法的特征举行进一步的优化,由于这个算法的底层会对一切的 unique value取hash值,应用这个hash值去近似的求distcint count, 因而我们能够在建立mapping时,将这个hash的求法设置好,增添doc时,一并盘算出这个hash值,如许 HyperLogLog++ 就无需再盘算hash值,而是直接运用

PUT /index/
{
    "mappings":{
        "my_type":{
            "properties":{
                "my_field":{
                    "type":"text",
                    "fields":{
                        "hash":{
                            "type":"murmu3"
                        }
                    }
                }
            }
        }
    }
}

掌握聚合的升降序

先依据色彩聚合,在聚合的效果上,再依据价钱举行聚合, 终究的效果中,依据价钱聚合的分组中升序排序, 这算是个鄙人转剖析时的排序技能

GET /index/type/_search
{
    "size":0,
     "aggs":{
         "group_by_color":{
             "term":{
                 "field":"color",
                 "order":{ # 
                     "avg_price":"asc"
                 }
             }
         },
         "aggs":{
             "avg_price":{
                 "avg":{
                     "field":"price"
                 }
             }
         }
     }
}

Percentiles Aggregation

盘算百分比, 常用它盘算如,在200ms内胜利接见网站的比率,在500ms内胜利接见网站的比例,在1000ms内胜利接见网站的比例, 或许是销售价为1000元的商品,占总销售量的比例, 销售价为2000元的商品占总销售量的比例等等

示例: 针对doc中的 load_time字段, 盘算出在差别百分比下面的 load_time_outliner状况

GET latency/_search
{
    "size": 0,
    "aggs" : {
        "load_time_outlier" : {
            "percentiles" : {
                "field" : "load_time" 
            }
        }
    }
}

相应 : 解读: 在百分之50的加载请求中,均匀load_time的时候是在445.0, 在99%的请求中,均匀加载时候980.1

{
    ...

   "aggregations": {
      "load_time_outlier": {
         "values" : {
            "1.0": 9.9,
            "5.0": 29.500000000000004,
            "25.0": 167.5,
            "50.0": 445.0,
            "75.0": 722.5,
            "95.0": 940.5,
            "99.0": 980.1000000000001
         }
      }
   }
}

还能够本身指定百分比跨度间隔

GET latency/_search
{
    "size": 0,
    "aggs" : {
        "load_time_outlier" : {
            "percentiles" : {
                "field" : "load_time",
                "percents" : [95, 99, 99.9] 
            }
        }
    }
}

优化: percentile底层运用的是 TDigest算法,用许多个节点实行百分比盘算,近似预计,有偏差,节点越多,越精准

能够设置compression的值, 默许是100 , ES限定节点的最多是 compression*20 =2000个node去盘算 , 由于节点越多,机能就越差

一个节点占用 32字节, 1002032 = 64KB

GET latency/_search
{
    "size": 0,
    "aggs" : {
        "load_time_outlier" : {
            "percentiles" : {
                "field" : "load_time",
                "percents" : [95, 99, 99.9],
                "compression":100 # 默许值100
            }
        }
    }
}

优化相干性得分

  • 第一种体式格局:

在content字段中全文检索 java elasticsearch时,给title中同时涌现java elasticsearch的doc的权重更加

"query": {
      "bool" : {# 前缀婚配
         "match":{
            "content":{
                 "query":"java elasticsearch"
            }
         },
         "should":[
             "match":{
                 "title":{
                     "query":"java elasticsearch",
                     "boost":2
                 }
             }
         ]
       } 
  }
  • 第二种: 替换写法,转变占用的权重比例
GET my_index/_doc/_search
{
  "query":{
     "should":[
      { "match":{"title":"this is"}},  # 1/3
      { "match":{"title":"this is"}},  # 1/3
      {
        "bool":{
         "should":[
           {"match":{"title":"this is"}}, # 1/6
           {"match":{"title":"this is"}}  # 1/6
           ]
       }
     }
   ] 
 }
}
  • 第三种: 假如不愿望运用相干性得分,运用下面的语法
GET my_index/_doc/_search
{
    "query": {
        "constant_score" : {
            "filter" : {
              "term" : { "title" : "this"} #
            },
            "boost" : 1.2
        }
    }
}
  • 第四种: 天真的查询

查询必需包括XXX,必需不包括YYY的doc

GET my_index/_doc/_search
{
  "query":{
    "bool": {
      "must":{
        "match":{
          "title":"this is a "
        }
      },
      "must_not":{
        "match":{
           "title":"another"
         }
       }
    }
  }
}
  • 第五种: 查询必需包括XXX,能够包括YYY,然则包括了YYY后它的权重就会削减指定的值

GET my_index/_doc/_search
{
  "query":{
    "boosting": {
      "positive":{
        "match":{
          "title":"this is a "
        }
      },
      "negative":{
        "match":{
           "title":"another"
         }
       },
       "negative_boost": 0.2
    }
  }
}
  • 第六种: 重打分机制
   "query": { 
       "match":{
           "title":{
               "query":"java elasticsearch",
               "minimum_should_match":"50%"
           }
       },
       "rescore":{ # 对全文检索的效果举行从新打分
           "window_size":50,  # 对全文检索的前50条举行从新打分
           "query": { 
               "rescore_query":{ # 关键字
                    "match_phrase":{ # match_phrase + slop 感知 term persition,孝敬分数
                       "title":{
                           "query":"java elasticsearch",
                           "slop":50
                  }
              }
          }
       }
   }
  • 第七种: 混用match和match_phrase进步召回率
  "query": { 
      "bool": {  
      "must":  {
          # 全文检索虽然能够婚配到大批的文档,然则它不能掌握词条之间的间隔
          # 能够java elasticsearch在Adoc中间隔很近,然则它却被ES排在效果集的背面
          # 它的机能比match_phrase高10倍,比proximity高20倍
         "match": {
            "address": "java elasticsearch" 
            } 
      },
      "should": {
         # 借助match_phrase+slop能够感知term position的功用,为间隔邻近的doc孝敬分数,让它们靠前分列
          "match_phrase":{
              "title":{
                  "query":"java elasticsearch",
                  "slop":50
              }
          }
      }
  }

迎接人人点赞支撑

  选择打赏方式
微信赞助

打赏

QQ钱包

打赏

支付宝赞助

打赏

  移步手机端
干货 Elasticsearch 知识点整顿 一

1、打开你手机的二维码扫描APP
2、扫描左则的二维码
3、点击扫描获得的网址
4、可以在手机端阅读此文章
未定义标签

本文来源:搜奇网

本文地址:https://www.sou7.cn/282276.html

关注我们:微信搜索“搜奇网”添加我为好友

版权声明: 本文仅代表作者个人观点,与本站无关。其原创性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容、文字的真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。请记住本站网址https://www.sou7.cn/搜奇网。

发表评论

选填

必填

必填

选填

请拖动滑块解锁
>>