Elasticsearch操做实践手册|建议收藏篇

我是啤酒就辣条。

但行好事,莫问前程。html

官方为咱们提供了多种语言操做Elasticsearch的API,能够很方便的在项目中操做。学习利用原生请求操做Elasticsearch,方便维护数据库,还能加快学习使用不一样语言的API。正则表达式

本博客使用kibana发起请求,使用kibana能够查看快捷键。数据库

索引操做

建立索引

建立索引使用PUT请求,后面跟上索引名称就行了,因为7.x默认type为_doc,因此后面没必要跟上type了。在PUT简单请求同时,能够加上JSON请求体,进行复杂建立。json

PUT /user
{
  "settings": {
    "index": {
      "number_of_shards": 3,  
      "number_of_replicas": 2 
    }
  },
  "mappings": {
    "properties": {
      "name": { "type": "text" },
      "age": {"type": "short"},
      "city":{"type": "keyword"}
    }
  }
}

建立索引user,能够经过参数setting设置分片和副本数,经过number_of_shards设置一共有3个分片,经过number_of_replicas给每一个分片设置2个副本,默认不指定的话,这两个参数都是1。经过mappings规定文档各个Filed插入类型。此外,还能够设置aliases字段,给索引建立别名,这样不只能够经过别名访问该索引,还能够定义查询条件、指定查询分片等等,详情请参考数组

删除索引

删除索引,使用DELETE请求。浏览器

DELETE /user

查看索引

查看索引,使用GET请求,能够查看索引设置的参数。缓存

删除以后,我又从新添加索引,没有设置settings,因此分片和副本都是1。app

你也能够经过在索引后面加参数来查看某一具体参数,如:elasticsearch

GET /user/_settings
GET /user/_mappings
GET /user/_aliases

修改索引部分设置

能够经过PUT请求修改部分索引的settings,例如,分片副本数量能够修改,可是分片数量不能够经过这种方式修改。ide

PUT /user/_settings
{
  "number_of_replicas": 3 
}

能够经过以上请求,修改分片副本。

文档操做

建立好索引,来看下文档的增删改查,这是平常业务用的最多的地方。

插入文档

新增文档使用PUTPOST请求。

PUT /<target>/_doc/<_id>

POST /<target>/_doc/

PUT /<target>/_create/<_id>

POST /<target>/_create/<_id>

target为索引名称,_doc为默认type。经过前两种请求可看出,id能够自行指定,也能够由ES自动生成。_create能够保证只有当文档不存在的时候进行插入,而_doc还能够用于文档更新。

POST /user/_doc/1
{
  "name":"pjjlt",
  "age":26,
  "city":"sjz"
}

更新文档

更新文档可使用PUT或者POST请求关键字,全量更新。

POST /user/_doc/1
{
  "name":"pjjlt",
  "age":3,
  "city":"sjz"
}

还能够经过_update命令局部更新,所谓局部更新,是讲请求体内不须要加入所有字段,只加入须要修改的字段就好,其余字段不变。全量更新会替换整个文档。

POST /user/_update/1
{
  "doc":{
    "age": 26
  }
}

此外还能够经过脚本修改,例如将全部存在age字段的文档,其值改为5岁。

POST /user/_update_by_query
{
  "script": {
    "source": "ctx._source['age']=5" 
  },
  "query": {
    "bool": {
      "must": [
        {
          "exists": {
            "field": "age"
          }
        }
      ]
    }
  }
}

此外update_update_by_query字段还能够修改Filed,例如将name修改为name1,这块内容使用较少,如感兴趣,请参考官方文档。

删除文档

删除文档可使用DELEETE请求,删除指定id的文档,也可使用_delete_by_query,删除指定条件下的文档。

DELETE /user/_doc/1
POST /user/_delete_by_query
{
  "query": {
    "match": {
      "name": "pjjlt"
    }
  }
}

查找文档

查找文档是ES操做最精彩的部分,这里只介绍简单的查询,复杂查询、聚合查询后面会介绍。

根据id查询某文档。

GET /user/_doc/1

查找某索引下的所有文档

GET /user/_search?pretty

pretty参数在浏览器中才会发挥做用,格式化返回json的。以上这条命令默认返回10条数据,想返回更多数据能够添加size字段。

GET /user/_search?pretty&size=20

能够看出,数据部分在hits里面,Spring提供的elasticsearch客户端会有对应的实体类,在项目中很方便的使用。下面看下这几部分的含义。

元素 含义
took 运行查询须要多长时间
time_out 请求是否超时
_shards 搜索了多少分片,多少成功
多少跳过,多少失败
hits.total 总共有多少数据
hits._max_score 查询到的文档中,关联度最大文档分数
hits.hits._source 查询到的数据
hits.hits.id 某文档的主键

批量操做

批量操做是指,一批命令同时执行(减小IO),这些命令不必定是同种类型。

使用_bulk命令能够进行文档的批量增删改。

POST _bulk
{ "update" : { "_index" : "user", "_id" : "1" } }
{ "doc" : {"age" : 18} }
{ "create" : { "_index" : "user", "_id" : "2" } }
{ "name" : "小明","age":32,"city":"beijing" }
{ "create" : { "_index" : "user", "_id" : "3" } }
{ "name" : "小红","age":21,"city":"sjz" }
{ "create" : { "_index" : "user", "_id" : "4" } }
{ "name" : "mark","age":22,"city":"tianjin" }
{ "delete" : { "_index" : "user", "_id" : "4" } }

以上命令更新了id为1文档的年龄,新增id为二、三、4的文档,再删除id为4的文档。

上边的命令堆在一块儿不方便看,下面单独写看,方便读者查看。

批量新增

POST _bulk
{ "create" : { "_index" : "user", "_id" : "2" } }
{ "name" : "小明","age":32,"city":"beijing" }
{ "create" : { "_index" : "user", "_id" : "3" } }
{ "name" : "小红","age":21,"city":"sjz" }

{ "index" : { "_index" : "user", "_id" : "4" } }
{ "name" : "mark","age":22,"city":"tianjin" }

create命令是只有文档不存在,才会插入,index会判断若是存在就更新,不存在就插入。

批量更新

POST _bulk
{ "update" : { "_index" : "user", "_id" : "1" } }
{ "doc" : {"age" : 18} }
{ "update" : { "_index" : "user", "_id" : "2" } }
{ "doc" : {"age" : 20} }

和新增同样,update命令下一行须要紧跟这data数据。

批量删除

POST _bulk
{ "delete" : { "_index" : "user", "_id" : "3" } }
{ "delete" : { "_index" : "user", "_id" : "4" } }

批量查找

批量查找,使用_mget关键字,批量查找若是不跨越索引,也具备简写形式。

GET /_mget
{
  "docs": [
    {
      "_index": "user",
      "_id": "1"
    },
    {
      "_index": "user",
      "_id": "2"
    }
  ]
}

# 还能够简写形式
POST /user/_mget
{
  "ids": [
    "1",
    "2",
    "3"
  ]
}

DSL查询

Elasticsearch提供了一个完整的基于JSON的查询DSL(领域特定语言)来定义查询。能够将查询DSL看做查询的AST(抽象语法树),它由两种类型的子句组成: Leaf query clauses(叶查询子句)和 Compound query clauses(复合查询子句)

以上摘自官网,简单来讲,DSL就是将查询条件放到JSON中,进行查询。

Leaf query clauses在特定字段上查找特定的值,例如matchtermrange查询等等。

Compound query clauses将叶查询子句和其余符合查询子句结合起来,例如bool查询等等。

match

match是一个标准查询,当查询一个文本的时候,会先将文本分词。当查询确切值的时候,会搜索给定的值,例如数字、日期、布尔或者被not_analyzed的字符串。
GET /user/_search
{
  "query": {
    "match": {
      "name":"小明"
    }
  }
}

上面的操做会先将“小明”分词为“小”、“明”(固然具体还要看你的分词器),而后再去全部文档中查找与之相匹配的文档,并根据关联度排序返回。

match_phrase

match_phrase会保留空格,match会把空格忽略。
GET /user/_search
{
  "query": {
    "match_phrase": {
      "name":"小 明"
    }
  }
}

注意,分词是空格会给前一个元素,好比上面的字符串分子以后是,“小 ”,“明”。

multi_match

多字段查询,一个查询条件,看全部多个字段是否有与之匹配的字段。后面咱们也可使用 should更加灵活。
GET /user/_search
{
  "query": {
    "multi_match": {
      "query":    "哈哈", 
      "fields": [ "name","city" ] 
    }
  }
}

match_all

匹配全部,并可设置这些文档的 _score,默认 _score为1,辣条君认为这里没有计算 _score,因此速度会快不少。
GET /user/_search
{
  "query": {
    "match_all": { "boost" : 1.2 }
  }
}

boost参数能够省略,默认是1。

term

term是一种彻底匹配,主要用于精确查找,例如数字、ID、邮件地址等。
GET /user/_search
{
  "query": {
    "term": {
      "age": 18
    }
  }
}

terms

terms是term多条件查询,参数能够传递多个,以数组的形式表示。
GET /user/_search
{
  "query": {
    "terms": {
      "age":[18,21]
    }
  }
}

wildcard

通配符,看示例容易理解,通配符能够解决分词匹配不到的问题,例如'haha' 能够经过'*a'匹配。
GET /user/_search
{
  "query": {
    "wildcard": {
      "name":"*a"
    }
  }
}

exists

查看某文档是否有某属性,返回包含这个 Filed的文档。
GET /user/_search
{
  "query": {
    "exists": {
      "field": "name"
    }
  }
}

fuzzy

返回与查询条件相同或者类似的匹配内容。
GET /user/_search
{
  "query": {
    "fuzzy": {
      "name":"mjjlt"
    }
  }
}

搜索条件是mjjlt,能够搜出来name为pjjlt的文档。这个操做是否是在百度的时候常常见到呢?

ids

多id查询,这个id是主键id,即你规定或者自动生成那个。
GET /user/_search
{
  "query": {
    "ids": {
      "values":[1,2,3]
    }
  }
}

prefix

前缀匹配
GET /user/_search
{
  "query": {
    "prefix": {
      "name":"pj"
    }
  }
}

range

范围匹配。参数能够是 gt(大于)、 gte(大于等于)、 lt(小于)、 lte(小于等于)
GET /user/_search
{
  "query": {
    "range": {
      "age":{
          "gt":1,
          "lt":30
      }
    }
  }
}

regexp

正则匹配。value是正则表达式,flags是匹配格式,默认是ALL,开启全部。更多格式 请戳
GET /user/_search
{
  "query": {
    "regexp": {
      "name":{
          "value": "p.*t",
          "flags": "ALL"
      }
    }
  }
}

bool

bool 能够用来组合其余子查询。其中常包含的子查询包含:must、filter、should、must_not

must

must内部的条件必须包含,内部条件是and的关系。如查看全部name中包含“小”而且age是32的用户文档。

GET /user/_search
{
  "query": {
    "bool" : {
      "must": [
        {"term" : { "name" : "小" }},
        {"term" : { "age" : 32 }}
      ]
    }
  }
}

filter

filter是文档经过一些条件过滤下,这是四个关键词中惟一和关联度无关的,不会计算_score,常用的过滤器会产生缓存。

GET /user/_search
{
  "query": {
    "bool" : {
      "filter": {
        "term" : { "name" : "小" }
      }
    }
  }
}

对比两张图能够看出,filter并无计算_score,搜索速度较快。

must_not

这个和must相反,文档某字段中必定不能包含某个值,至关于“非”。

should

should能够看作or的关系,例以下面查询name包含"小"或者年龄是18岁的用户。

GET /user/_search
{
  "query": {
    "bool" : {
      "should": [
        {"term" : { "name" : "小" }},
        {"term" : { "age" : 18 }}
      ]
    }
  }
}

聚合查询

Elasticsearch除全文检索功能外提供的针对Elasticsearch数据作统计分析的功能。能够查询某组数据的最大最小值,分组查询某些数据。

  • Metric(指标): 指标分析类型,如计算最大值、最小值、平均值等等 (对桶内的文档进行聚合分析的操做)
  • Bucket(桶): 分桶类型,相似SQL中的GROUP BY语法 (知足特定条件的文档的集合)
  • Pipeline(管道): 管道分析类型,基于上一级的聚合分析结果进行在分析

Metric(指标)数据

经常使用数学操做

这里经常使用的数学操做有 min(最小)、 max(最大)、 sum(和)、 avg(平均数)。注意这些操做只能输出一个分析结果。使用方式大同小异。
GET /user/_search
{
    "aggs" : {
        "avg_user_age" : 
        { 
          "avg" : { "field" : "age" } 
        }
    }
}

以上示例查询全部用户的平均年龄,返回全部文档和聚合查询结果。aggs是聚合查询关键词,avg_user_age是查询名称,用户能够自行定义。

cardinality

计算某字段去重后的数量
GET /user/_search
{
    "aggs" : {
        "avg_user" : 
        { 
          "cardinality" : { "field" : "age" } 
        }
    }
}

能够计算,全部文档中年龄不相同的文档个数。

percentiles

对指定字段的值按从小到大累计每一个值对应的文档数的占比,返回指定占比比例对应的值。

默认统计百分比为[ 1, 5, 25, 50, 75, 95, 99 ]

GET /user/_search
{
    "aggs" : {
        "avg_user" : 
        { 
          "percentiles": { "field" : "age" } 
        }
    }
}

# 返回值(省略文档部分,只分析结果部分)
  "aggregations" : {
    "avg_user" : {
      "values" : {
        "1.0" : 12.0,
        "5.0" : 12.0,
        "25.0" : 20.25,
        "50.0" : 29.0,
        "75.0" : 57.75,
        "95.0" : 123.0,
        "99.0" : 123.0
      }
    }
  }

能够看出,前1%的用户小于12岁,5%的用户小于12岁,25%的用户小于20.25岁,50%的用户小于29岁。。。

percentile_ranks

percentiles是经过百分比求出文档某字段,percentile_ranks是给定文档中的某字段求百分比。
GET /user/_search
{
    "aggs" : {
        "avg_user" : 
        { 
          "percentile_ranks": 
            { 
              "field" : "age",
              "values" : [18, 30]
            } 
        }
    }
}

# 返回值(省略文档部分,只分析结果部分)
  "aggregations" : {
    "avg_user" : {
      "values" : {
        "18.0" : 18.51851851851852,
        "30.0" : 54.44444444444445
      }
    }
  }

能够看出,小于等于18岁的用户有18.52%,小于等于30岁的用户有54.4%。

top_hits

top_hits能够获得某条件下top n的文档。
GET /user/_search
{
  "aggs": {
    "avg_user" : {
      "top_hits": {
          "sort": [
          {
            "age": {
              "order": "asc"
            }
          }
        ],
        "size": 1
      }
    }
  },
  "size": 0
}

取年龄最小的那一个。

Bucket(桶)

相似于分组的概念。

terms

根据给定的filed分组,返回每组多少文档。
GET /user/_search
{
    "aggs" : {
        "avg_user" : 
        { 
          "terms": {
                  "field": "city"
                }
        }
    }
}

以上根据城市分组,看每一个城市有多少用户。

ranges

根据区间分组
GET /user/_search
{
  "aggs": {
    "price_ranges": {
      "range": {
        "field": "age",
        "ranges": [
          { "to": 20 },
          { "from": 20, "to": 30 },
          { "from": 30 }
        ]
      }
    }
  }
}

能够查看每一个年龄层的用户数量。

还有些颇有趣的指令,例如[IP range]能够根据ip段区间分组,之后用到再说吧,但愿文本能够不段更新的说...

相关文章
相关标签/搜索