ElasticSearch 零基础入门(1): 基本概念和操作

Tags: ElasticSearch 

目录

说明

Elasticsearch 是一个准实时的分布式搜索分析引擎,提供索引、搜索和分析功能。 Logstash、xxBeats 是配套的数据导入工具,Kibana 提供了可视化页面。

学习资料: es官网文档ElasticSearch GuideElasticSearch Apis

笔记列表:ElasticSearch

基本概念:Document、Index 和 Mapping

Index: es 中的 Document 的组织单位,每个 Document 都隶属一个 Index。

Mapping: index 中记录 Document 的每个 field 的数值类型等信息,影响 es 索引文档时的行为。

Document:一份序列化成 json 格式的文档数据,它由多个 field 组成,每个 field 是一个 key-value。

与关系型数据库类比:

                   关系型数据库                     ES  
----------------------------------------------------------------------------
管理的数据单元     包含多个列的关系型行记录        包含多个k-v field 的json 字符串
数据的组织单位     数据表                          Index 索引
数据类型描述       建表语句                        Index 的 Mapping
                   Table                           Index 
                   Row                             Document 
                   Column                          Field 
                   Schema                          Mapping
                   SQL                             DSL
             

Document 的每个 field 可以使用不同的数据类型,es 根据 field 的类型使用不同的索引方式,例如:

  1. text fields 存储在倒排索引中
  2. numeric 和 geo 存储在 BKD tree 中

Mapping 可以手动创建,或者启用 dynamic mapping, 让 es 自动添加并推断 field 的数据类型。

ES 的特点:

  1. 文档数据(Document)写入后会在 1s 之内完成索引、可被搜索
  2. 为 text 类型的 field 建立「倒排索引/ inverted index」,支持快速的全文搜索

Index 操作

Es 检查运行状态:

curl http://127.0.0.1:9200

创建 Index

Index 创建时请求 body 中可以设置的内容分为 aliases、mappings 和 settings 三部分,Create index API。aliases 定义 index 的别名、mappings 定义 Document 中每个 field 的类型和配置,settings 定义 index 的存储副本以及其它 es 支持的功能,譬如分词。

创建 Index 并设置 Mapping:

PUT /my-index-000001?pretty
{
  "mappings": {
    "properties": {
      "age":    { "type": "integer" },  
      "email":  { "type": "keyword"  }, 
      "name":   { "type": "text"  }     
    }
  }
}

PUT 上传的内容就是 Mapping,age、email、name 是 Document 中的 field 名称,type 是 field 的数值类型。

删除 Index

DELETE /my-index-000001

aliases 简要

Aliases

PUT /test
{
  "aliases": {
    "alias_1": {},
    "alias_2": {
      "filter": {
        "term": { "user.id": "kimchy" }
      },
      "routing": "shard-1"
    }
  }
}

mappings 详解

文档:Mapping

mappings 可以在创建 index 时显式创建,也可以动态生成。动态模式下,es 自动将新发现的 field 添加到 mapping 中。

mappings 的配置参数在 API 文档中可以找到:Elastic Api->Index Apis->Create Index Api->Mapping Parameters。mapping 的配置参数有的作用于 mappings 自身,譬如 dynamic、properties,有的是作用于 properties 中的 field 例如下面的 copy_to。

PUT my-index-000001
{
  "mappings": {
    "dynamic": "false",
    "properties": {
      "first_name": {
        "type": "text",
        "copy_to": "full_name" 
      },
      "last_name": {
        "type": "text",
        "copy_to": "full_name" 
      },
      "full_name": {
        "type": "text"
      }
    }
  }
}

dynamic 表示是否自动更新 mapping。写入的文档中如果含有 mapping 中未定义的 fields ,行为取决于 dynamic 参数的值:

Dynamic 为 true:  自动创建一个 field 并推测出类型;
Dynamic 为 false: 写入成功,新增的字段不能被索引,只会出现在_source中;
Dynamic 为 strict:文档写入失败;

properties 中包含了对所有 field 的说明(以 field name 为 key)。properties 是 mapping 配置的主要部分,掌握 mapping 的关键是掌握 es 支持的 field data type 。每种 field data type 都有自己的适用参数,在 API 文档中可以找到:Elastic Api->Index Apis->Create Index Api->Field data types。适用于多种 field data type 的参数见 Mapping Parameters,注意其中有一些是适用于 mapping 的譬如 dynamic,结合目标 field data type 自身文档适用。

field data types 一旦定义后不能修改,如果要修改,必须用 Reindex API 重建索引。

mapping 的 fields 参数需要特别注意,通过它可以为一个 field 指定多种类型。譬如下面的 city 是 text 类型,如果某些场合下 需要把 city 当作 keyword 类型处理,在 fields 中新增一个 keyworld 类型的 field,名字自定义。 下面的 city.raw 就会被作为 keyword 类型对待。

PUT my-index-000001
{
  "mappings": {
    "properties": {
      "city": {
        "type": "text",     <-- 第一个类型 text
        "fields": {         
          "raw": {          <-- 在 fields 属性中设置一个使用其它类型的 field,名为 raw,类型为 keyword
            "type":  "keyword"   
          }
        }
      }
    }
  }
}

在一次查询中可以同时使用 city 和 city.raw:

GET my-index-000001/_search
{
  "query": {
    "match": {
      "city": "york" 
    }
  },
  "sort": {
    "city.raw": "asc" 
  },
  "aggs": {
    "Cities": {
      "terms": {
        "field": "city.raw" 
      }
    }
  }
}

mapping 的更多特性到 Mapping Parameters 中探索。

field data type

field 可以使用以下数据类型,不同版本的支持情况可能不同,详情见 Field data types

数组类型不需要专门定义,每个 field 的数值都可以是一个数组列表。

常规类型:Common types

  1. binary
  2. boolean
  3. keywords:keyword/constan_keyword/wildcard
  4. numbers:long/integer/short/byte/double/float/halt_float/scaled_float/unsigned_long
  5. dates:date/date_nanos
  6. alias:用于定义别名

对象类型:Objects and relational types

  1. object:json对象可以被自动mapping
  2. flattened:值为 json 类型的 field
  3. nested
  4. join

结构化类型:Structured data types

  1. range:integer_range/float_range/long_range/double_range/date_range/ip_range
  2. ip:ip地址
  3. version:https://semver.org/ 类型的版本号
  4. murmur3:一个插件,用于生成 field 的哈希值

聚合数据类型:Aggregate data types

  1. aggregate_metric_double
  2. histogram

搜索文本类型:Text Search types

  1. text fields:text/match_only_text
  2. annotated-text:插件
  3. completion
  4. search_as_you_type
  5. token_count

文档排名类型:Document ranking types

  1. dense_vector
  2. sparse_evctor
  3. rank_feature
  4. rank_features

地理位置类型:Spatial data types

  1. geo_point
  2. geo_shape
  3. point
  4. shape

其它类型:Other types

  1. percolator

settings 简要

settings 中可以设置的内容较多,这里只简单说明,给出相关文档的链接。

PUT /my-index-000001   # 创建时设置 settings
{
  "settings": {
    "index": {
      "number_of_shards": 3,
      "number_of_replicas": 2
    }
  }
}

PUT /my-index-000001  # 可以省略 index
{
  "settings": {
    "number_of_shards": 3,
    "number_of_replicas": 2
  }
}


PUT /test    # 和 mappings 一起设置
{
  "settings": {
    "number_of_shards": 1
  },
  "mappings": {
    "properties": {
      "field1": { "type": "text" }
    }
  }
}

settings 中和 Index 直接相关的配置有两类,分别是 static 和 dynamic 类型。static 类型的配置只能在创建 Index 的时候赋值,dynamic 类型的配置可以创建 Index 之后修改。在 Index Settings 中可以找到所有配置项目:

static:

index.number_of_shards
index.number_of_routing_shards
index.codec
index.routing_partition_size
index.soft_deletes.enabled
index.soft_deletes.retention_lease.period
index.load_fixed_bitset_filters_eagerly
index.shard.check_on_startup

dynamic:

index.number_of_replicas
index.auto_expand_replicas
index.search.idle.after
index.refresh_interval
index.max_result_window
index.max_inner_result_window
index.max_rescore_window
index.max_docvalue_fields_search
index.max_script_fields
index.max_ngram_diff
index.max_shingle_diff
index.max_refresh_listeners
index.analyze.max_token_count
index.highlight.max_analyzed_offset
index.max_terms_count
index.max_regex_length
index.query.default_field
index.routing.allocation.enable
index.routing.rebalance.enable
index.gc_deletes
index.default_pipeline
index.final_pipeline
index.hidden

特别注意,es 其它功能模块的设置也通过 settings 设置,settings_in_other_index_modules。比如分词配置 analysis。

analysis 配置

test-analyzer

创建 index 的时候指定分词规则:

PUT my-index-000001
{
  "settings": {
    "analysis": {
      "analyzer": {
        "std_folded": { 
          "type": "custom",
          "tokenizer": "standard",
          "filter": [
            "lowercase",
            "asciifolding"
          ]
        }
      }
    }
  },
  "mappings": {
    "properties": {
      "my_text": {
        "type": "text",
        "analyzer": "std_folded"    # 绑定分词器
      }
    }
  }
}

使用 Index 的分词配置分词,注意用 GET 方法,body 中是要分词的内容:

GET my-index-000001/_analyze    
{
  "analyzer": "std_folded",       # 方式一,指定分词器名称
  "text":     "Is this déjà vu?"  # 目标文本
}

GET my-index-000001/_analyze 
{
  "field": "my_text",             # 方式二,指定配置了分词器的 field
  "text":     "Is this déjà vu?"  # 目标文本
}

分词结果:

{
  "tokens": [
    {
      "token": "is",
      "start_offset": 0,
      "end_offset": 2,
      "type": "<ALPHANUM>",
      "position": 0
    },
    {
      "token": "this",
      "start_offset": 3,
      "end_offset": 7,
      "type": "<ALPHANUM>",
      "position": 1
    },
    {
      "token": "deja",
      "start_offset": 8,
      "end_offset": 12,
      "type": "<ALPHANUM>",
      "position": 2
    },
    {
      "token": "vu",
      "start_offset": 13,
      "end_offset": 15,
      "type": "<ALPHANUM>",
      "position": 3
    }
  ]
}

查看 Index

查看 es 中所有 index:

GET /_cat/indices?v

health status index                          uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   .kibana-event-log-7.9.2-000001 BXulL2qmTTq2FYYOYdNqbQ   1   0          1            0      5.5kb          5.5kb
green  open   .apm-custom-link               CS8LkfBvRKGdSXjI0ky6tw   1   0          0            0       208b           208b
green  open   .kibana_task_manager_1         569Jhi3NS8etY8pYF4jxvg   1   0          6          267    136.2kb        136.2kb
green  open   kibana_sample_data_ecommerce   _6pu_ggDQCSLwL9jvrA-Fg   1   0       4675            0      4.7mb          4.7mb
green  open   .apm-agent-configuration       t9t6VR2KQi-YDewFQjI0Fw   1   0          0            0       208b           208b
green  open   .kibana_1                      pEI_2VXrTRagNq_fyWd5eg   1   0         75            1     12.6mb         12.6mb
yellow open   my-index-000001                6mmUoVrASWSTBWQjKDicqg   1   1          0            0       208b           208b

查看 Index my-index-000001 的 Mapping:

GET  /my-index-000001/_mapping

{
  "my-index-000001" : {
    "mappings" : {
      "properties" : {
        "age" : {
          "type" : "integer"
        },
        "email" : {
          "type" : "keyword"
        },
        "name" : {
          "type" : "text"
        }
      }
    }
  }
}

Index 自动创建

ES 支持在写入的 document 的时候自动创建不存在的 index:

PUT /new-index-000001/_doc/1
{
      "age":    11,  
      "email":  "[email protected]", 
      "name":   "小王"   
}

查看:

GET /new-index-000001/

Document 操作

写入 Document(create/index/update)

Document 的写入分为 create、update、index 等几种方式。PUT 方法用于创建(Create)和重新索引(Index),POST 方法用于(Create)和更新(Update)。

my-index-000001 是目标 index,_doc 是 ES 定义的接口路径,1 是要写入的 Document 的 id,Body 是 Document 内容。

Create Document:PUT 需要指定文档 ID,如果ID已经存在则报错;POST 不指定 ID,由 ES 自动分配 ID。

# Create:PUT 方式需要指定ID,如果 ID 已经存在报错
PUT /my-index-000001/_create/1      
PUT /my-index-000001/_doc/1?op_type=create  # 另一种写法
{
      "age":    11,  
      "email":  "[email protected]", 
      "name":   "小王"   
}
# Create:POST 方式不需要指定,es 自动分配 ID
POST /my-index-000001/_doc
{
      "age":    11,  
      "email":  "[email protected]", 
      "name":   "小王"   
}

Index Document:PUT 方法,全量替换,会将 ID 对应的旧文档删除,然后新建并且 _version 增加 1。

# Index:PUT,指定 ID,不设置 op_type,_version+1 
PUT /my-index-000001/_doc/1
{
      "age":    11,  
      "email":  "[email protected]", 
      "name":   "小王"   
}

Update Document:POST方式,使用 _update api,修改旧文档,_version 增加 1。

# Create:POST 方式不需要指定,es 自动分配 ID,_version+1
POST /my-index-000001/_update/1
{
      "age":    12,  
      "email":  "[email protected]", 
      "name":   "小王"   
}

批量写入 Document

向 _bulk 接口传入的 body 中,可以包括 create/update/index/delete 四种操作,单条失败不影响其它操作,返回每条的操作结果。

wget https://raw.githubusercontent.com/elastic/elasticsearch/master/docs/src/test/resources/accounts.json
curl -H "Content-Type: application/json" -XPOST "localhost:9200/banke/_bulk?pretty&refresh" --data-binary "@accounts.json"
POST _bulk
{ "index" : { "_index" : "test", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_id" : "2" } }
{ "create" : { "_index" : "test2", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }

查询 Document:通过 ID 查询

查询 ID 为 1 的 Document:

GET  /my-index-000001/_doc/1

{
  "_index" : "my-index-000001",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "age" : 11,
    "email" : "[email protected]",
    "name" : "小王"
  }
}

返回的结果中带 _ 前缀 field 是 Document 的 Metadata fields。

_mget 接口支持一次请求包含多个查询:

GET /_mget
{
    "docs" : [
        {
            "_index" : "test",
            "_id" : "1"
        },
        {
            "_index" : "test",
            "_id" : "2"
        }
    ]
}
```### Document Metadata fields

查询的 Document 的时候会发现,返回了很多带有 `_` 前缀的 field,它们是 es 内置的 metadata fields:

```sh
GET  /my-index-000001/_doc/1

{
  "_index" : "my-index-000001",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "age" : 11,
    "email" : "[email protected]",
    "name" : "小王"
  }
}

其中 _version 是 Document 当前内容的版本,每修改一次加1,但是 es 只是给出了 _version 计数,不支持查询历史版本内容,How to retrieve older version document from elasticsearch?

ES 支持的 Metadata fields ,不知道为啥没有包括返回的 _type、_version 等字段的说明,它们的含义需要到 Get Api 中查看。

found:

_type:
_seq_no: 
_primary_term:

_index: 文档隶属的 Index
_id:    文档自身的 ID
_source:文档原始的 json 数据 
_size:  _source 中内容的大小,单位为字节
_doc_count:
_field_names:
_ignored:
_routing:
_meta:
_tier

查询 Document:field 数值匹配查找

查找年龄为 11 的 Document,使用 query 的 term 语句:

GET /my-index-000001/_search
{
  "query": {
    "term": {
      "age": 11
    }
  }
}

数值匹配查找的结果是列表,hits.hits 是符合查询条件的文档列表,hits 中其它字段是对查询结果的说明:

{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "my-index-000001",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "_source" : {
          "age" : 11,
          "email" : "[email protected]",
          "name" : "小王"
        }
      }
    ]
  }
}

_msearch 接口支持一次传入多个查询:

POST kibana_sample_data_ecommerce/_msearch
{}
{"query" : {"match_all" : {}},"size":1}
{"index" : "kibana_sample_data_flights"}
{"query" : {"match_all" : {}},"size":2}

删除 Document

DELETE /my-index-000001/_doc/1
{
  "_index" : "my-index-000001",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 6,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 5,
  "_primary_term" : 1
}

查询已删除的文档:

GET /my-index-000001/_doc/1
{
  "_index" : "my-index-000001",
  "_type" : "_doc",
  "_id" : "1",
  "found" : false
}

参考

  1. 李佶澳的博客
  2. es官网文档
  3. Install Kibana With Docker
  4. Install Elasticsearch With Docker
  5. Elastic Stack Doc
  6. Running the Elastic Stack On Docker

推荐阅读

Copyright @2011-2019 All rights reserved. 转载请添加原文连接,合作请加微信lijiaocn或者发送邮件: [email protected],备注网站合作

友情链接:  系统软件  程序语言  运营经验  水库文集  网络课程  微信网文  发现知识星球