ElasticSearch7 学习笔记

39 篇文章 1 订阅
12 篇文章 0 订阅

集群内的原理

空集群

https://www.elastic.co/guide/cn/elasticsearch/guide/current/_an-empty-cluster.html

  1. ElastiSearch天生就是 分布式的 , 其强大之处在于水平扩容(增加节点)。
  2. 一个ElasticSearch实例就是一个节点,一个节点就是一个集群(只不过是空集群)。
  3. 拥有相同cluster.name的节点,组成一个集群,共同抗压。
  4. 选举主节点,主节点管理集群级别变更,增加删除节点、增加删除索引。从节点管理文档级别的操作
  5. 每个节点都知道所有文档的存储位置,请求发送到任何节点都ok。

åå«ç©ºå容èç¹çé群

索引

索引是保存数

据的地方,是指向1或N个具体分片的逻辑命名空间(类似mysql schema)。

索引名必须小写,不能以下划线开头,不能包含逗号。

分片

  1. 一个分片存储一部分数据。
  2. 一个分片就是一个lucence实例。
  3. 分片被分配到集群的各个节点里。
  4. 扩容缩容会移动分片,故不影响数据查询。
  5. 一个分片可以是  分片或者 副本 分片。
  6. 缺失主分片的索引无法正常工作。

创建索引onionli,并指向3个主分片,且每个主分片一个副本分片,可见所有分片将会被分布在两个节点上。

PUT /onionli
{
   "settings" : {
      "number_of_shards" : 3,
      "number_of_replicas" : 1
   }
}

添加故障转移(运维类)

https://www.elastic.co/guide/cn/elasticsearch/guide/current/_add_failover.html

水平扩容(运维类)

https://www.elastic.co/guide/cn/elasticsearch/guide/current/_scale_horizontally.html

  • 水平扩容后,每个节点的分片数更少,分片是Lucense实例,其独占资源更多,故效率更高。
  • 节点数量扩容,总结点数大于主分片+副本分片数,可以运行中调整索引副本数,副本越多,检索效率也越高。
  • 节点数量不变,盲目增加分片数,会降低效率。

æ¥æä¸ä¸ªèç¹çé群

应对故障(运维类)

  1. 某节点宕机,其上某索引的部分主分片丢失,该索引无法正常工作,此时集群状态为红色(存在主分片无法正常工作则红)。
  2. 从新选举主节点,提升副本分片为主分片,副本分片减少,此时集群状态为黄色(部分副本分片丢失或异常)。
  3. 等节点重启,集群尝试恢复,恢复成功后,集群状态回归绿色。

https://www.elastic.co/guide/cn/elasticsearch/guide/current/_coping_with_failure.html

集群的健康

  • green 健康
  • yellow 主分片正常,部分副本分片异常
  • red 存在主分片异常(某节点宕机,其上主分片丢失,缺失主分片的索引无法正常工作)

文档路由到分片

解释为何创建索引时要固定分片,文档会根据文档id进行hash后mod固定的分片数量,以确定文档位于哪个分片。所以若分片数变化,则之前分配好的文档就会都丢失了。

根据公式

shard = hash(routing) % number_of_primary_shards

所有的文档 API( get 、 index 、 delete 、 bulk 、 update 以及 mget )都接受一个叫做 routing的路由参数 ,通过这个参数我们可以自定义文档到分片的映射。一个自定义的路由参数可以用来确保所有相关的文档——例如所有属于同一个用户的文档——都被存储到同一个分片中。

索引相关

获取索引的映射(索引中会存储哪些字段,每个字段是啥类型,是什么格式)

GET /onion/_mapping

文档元数据

_index(文档归属索引)

  • 索引是保存数据的地方,是指向1或N个具体分片的逻辑命名空间(类似mysql schema)。
  • 索引名必须小写,不能以下划线开头,不能包含逗号。

_type(文档类型)

  • 文档虽属于同一索引,但是可以继续细分类型,_type可以用于同索引下的文档进行二次逻辑分类。
  •  _type 命名可以是大写或者小写,但是不能以下划线或者句号开头,不应该包含逗号, 并且长度限制为256个字符

_id

  • ID 是一个字符串,当它和 _index 以及 _type 组合就可以唯一确定 Elasticsearch 中的一个文档。 当你创建一个新的文档,要么提供自己的 _id ,要么让 Elasticsearch 帮你生成。

对象指json,对象内部可嵌套对象。文档大部分等于对象,在存在嵌套时特指根对象。

插入文档

由于es7已经完全将type给废弃了,所以插入文档的语句中原本type的位置变为_doc或_create

post /{index}/_doc/{id}     

这种方式不论是否存在都能插入成功,不存在则纯插入,存在则更新文档和版本号。

post /{index}/_doc           

这种方式系统会帮您自动创建id。

post /{index}/_create/{id}

这种方式会在插入前校验文档是否存在,存在则不插,不存在则插入,并会返回元数据和一个 201 Created 的 HTTP 响应码

纯插

post /onion/_doc/id
{
    "name":"lisi",
    "birth":"2021-05-20"
}

查询文档

简单查询

拿所有字段slect * 

GET /onionli/typeA/id1?pretty pretty表示json化打印

返回found=true

{
   "_index": "onionli",
   "_type": "typeA",
   "_id": "id1",
   "_version": 2,
   "_seq_no": 1,
   "_primary_term": 1,
   "found": true,
   "_source": {
      "name": "28",
      "sex": 1
   }
}

拿部分字段select name,sex

先存入一个新文档
put /onionli/typeA/id2
{
    "name":"magic",
    "sex":"0",
    "age":10
}

只查这个文档的name和sex两个字段
GET /onionli/typeA/id2?_source=name,sex

只拿业务数据(忽略文档元数据)

GET /onionli/typeA/id2/_source

返回
{
   "name": "magic",
   "sex": "0",
   "age": 10
}

Query、Filter、Should、Must

https://blog.csdn.net/weixin_30446969/article/details/113491063

Query DSL 和 Filter DSL 的区别

先看案例,最外层是query,然后一个 bool 查询可以包含一个或多个查询字句 ,bool里面包含两部分:

  • 查询部分 must、should、mustNot等,这部分被称为query DSL
  • 过滤部分 filter,这部分被称为filter DSL
POST onion/_doc/_search
{
    "query": {
        "bool": {
            "must": [
               {
                   "match_all": {}
               }
            ],
            "filter": [
               {
                   "term": {
                      "name": {
                         "value": "lisi"
                      }
                   }
               }
            ]
        }
    }
}

Query DSL 和 Filter DSL的差别如下

Query DSL

  • 会进行全文检索。
  • 会进行相关性检查,比如查询包含run单词,如果包含这些单词:runs、running、jog、sprint,也被视为包含run单词。
  • 查询结果不会被缓存。
  • 查询结果会计算分值。

除非需要搜索文本,若纯粹当数据库使用,效率更低

Filter DSL

  • 仅仅校验field与传入的待匹配值是否相等。
  • 结果会缓存。
  • 查询结果不会贡献算分。

所以存粹当数据库使用,filter效率更高

Query DSL 中的must、should、must not

  • must:必须匹配,贡献算分
  • should:选择性匹配,贡献算分
  • must_not:查询字句,必须不能匹配
  • filter:必须匹配,不贡献算分

上图是一个 bool 查询,是对用户(user)进行搜索,城市必须是北京(beijing) ,性别必须是男(man),这个采用的是 filter,说明这个对算分是不会产生影响的,must_not 是一个 range 的查询:年龄大于等于 35 岁;should 里是一个数组,说明这个 should 中可以写多个条件,只要用户的名字是这两个中的一个就是满足条件的。

其实,bool 查询的子查询可以任意顺序出现,并且可以嵌套多个查询。

另外,should 的使用分两种情况:

  • bool 查询中只包含 should,不包含 must  或 filter 查询:如果在 bool 查询中没有 must、filter 子句,should 中必须至少满足一条查询(可以通过 minimum_should_match 来设置满足条件的个数或者百分比)。
  • bool 查询中同时包含 should 和 (must或filter) 查询:同时包含 should 和 (must或filter) 时,文档不必满足 should 中的条件,但是如果满足条件,会增加相关性算分。

查询模板

官网 https://www.elastic.co/guide/en/elasticsearch/reference/7.x/search-template.html

https://www.cnblogs.com/sanduzxcvbnm/p/12085136.html

往es里存两份文档

 PUT twitter/_doc/1
    {
      "user" : "双榆树-张三",
      "message" : "今儿天气不错啊,出去转转去",
      "uid" : 2,
      "age" : 20,
      "city" : "北京",
      "province" : "北京",
      "country" : "中国",
      "address" : "中国北京市海淀区",
      "location" : {
        "lat" : "39.970718",
        "lon" : "116.325747"
      }
    }
     
    PUT twitter/_doc/2
    {
      "user" : "虹桥-老吴",
      "message" : "好友来了都今天我生日,好友来了,什么 birthday happy 就成!",
      "uid" : 7,
      "age" : 90,
      "city" : "上海",
      "province" : "上海",
      "country" : "中国",
      "address" : "中国上海市闵行区",
      "location" : {
        "lat" : "31.175927",
        "lon" : "121.383328"
      }
    }

定义查询模板

  1. 使用_scripts端点将模板存储在集群状态中
  2. 在search template中使用mustache语法
{{#param1}}{{/param1}代表mybatis中的if标签,如果那个变量是false或null,则不会执行其中的片段。
{{#join}}array{{/join}}可以将数组转成逗号分隔的string
{{#toJson}}parameter{{/toJson}}将map或array转成json格式
{
  "from": {{from}}{{^from}}0{{/from}},
  "size": {{size}}{{^size}}5{{/size}},
  "sort": [{"price_effective_time": "asc"}],
  "query": {
        "bool": {
            "filter": [
               {
                  "exists": {
                     "field": "mer_item_no"
                  }
               }
               
               {{#startTime}}
               ,{
                   "range": {
                      "price_effective_time": {
                         "gte": "{{startTime}}",
                         "format": "yyyy-MM-dd HH:mm:ss"
                      }
                   }
               }
               {{/startTime}}
               
               {{#endTime}}
               ,{
                   "range": {
                      "price_effective_time": {
                         "lte": "{{endTime}}",
                         "format": "yyyy-MM-dd HH:mm:ss"
                      }
                   }
               }
               {{/endTime}}
               
               {{#midSet}}
               ,{
                   "terms": {
                      "merchandise_no": {{#toJson}}midSet{{/toJson}}
                   } 
               }
               {{/midSet}}
               
               {{#goodsNoSet}}
               ,{
                   "terms": {
                      "goods_no": {{#toJson}}goodsNoSet{{/toJson}}
                   } 
               }
               {{/goodsNoSet}}
               
               {{#merItemNoSet}}
               ,{
                   "terms": {
                      "mer_item_no": {{#toJson}}merItemNoSet{{/toJson}}
                   } 
               }
               {{/merItemNoSet}}
               
               {{#brandStoreSnSet}}
               ,{
                   "terms": {
                      "brand_store_sn": {{#toJson}}brandStoreSnSet{{/toJson}}
                   } 
               }
               {{/brandStoreSnSet}}
            ]
        }
    }
}

使用模板查询

GET twitter/_search/template
    {
      "id": "my_search_template",
      "params": {
        "my_field": "city",
        "my_value": "北京"
      }
    }

获取查询模板

GET _scripts/<templateid>

删除查询模板

DELETE _scripts/<templateid>

调试查询模板(验证模板生成的DSL)

GET _search/template
{
  "id": "你的templateId",
  "params": {
        "startTime":"2021-05-01 11:00:00",
        "endTime":"2021-08-01 11:00:00",
        "midSet":["1","2"],
        "goodsNoSet":["11","22"],
        "merItemNoSet":["111","222"],
        "brandStoreSnSet":["1111","2222"]
    }
}

调试的渲染结果
{
  "from": 0,
  "size": 5,
  "sort": [
    {
      "price_effective_time": "asc"
    }
  ],
  "query": {
    "bool": {
      "filter": [
        {
          "exists": {
            "field": "mer_item_no"
          }
        },
        {
          "range": {
            "price_effective_time": {
              "gte": "2021-05-01 11:00:00",
              "format": "yyyy-MM-dd HH:mm:ss"
            }
          }
        },
        {
          "range": {
            "price_effective_time": {
              "lte": "2021-08-01 11:00:00",
              "format": "yyyy-MM-dd HH:mm:ss"
            }
          }
        },
        {
          "terms": {
            "merchandise_no": [
              "1",
              "2"
            ]
          }
        },
        {
          "terms": {
            "merchandise_no": [
              "1",
              "2"
            ]
          }
        },
        {
          "terms": {
            "goods_no": [
              "11",
              "22"
            ]
          }
        },
        {
          "terms": {
            "goods_no": [
              "11",
              "22"
            ]
          }
        },
        {
          "terms": {
            "mer_item_no": [
              "111",
              "222"
            ]
          }
        },
        {
          "terms": {
            "mer_item_no": [
              "111",
              "222"
            ]
          }
        },
        {
          "terms": {
            "brand_store_sn": [
              "1111",
              "2222"
            ]
          }
        },
        {
          "terms": {
            "brand_store_sn": [
              "1111",
              "2222"
            ]
          }
        }
      ]
    }
  }
}

删除文档

成功则返回200,找不到文档则返回404

DELETE /onionli/typeA/id1

批量删除

bulk批量删除(不是批量越大越好,上线前请先调优最佳批量大小)

https://www.elastic.co/guide/cn/elasticsearch/guide/current/bulk.html

批量处理

原文链接:https://blog.csdn.net/weixin_39723544/article/details/109237175

es中的批量处理就是使用bulk进行操作。

bulk的操作类型

  • create 如果文档不存在就创建,但如果文档存在就返回错误
  • index 如果文档不存在就创建,如果文档存在就更新
  • update 更新一个文档,如果文档不存在就返回错误
  • delete 删除一个文档,如果要删除的文档id不存在,就返回错误
  • 其实可以看得出来index是比较常用的。还有bulk的操作,某一个操作失败,是不会影响其他文档的操作的,它会在返回结果中告诉你失败的详细的原因。

准备操作

  • 测试数据准备
  • 索引及映射结构准备
PUT example
PUT example/docs/_mapping
{
  "properties": {
    "id": {"type": "long"},
    "name": {"type": "text"},
    "counter": {"type": "integer"},
    "tags": {"type": "text"}
  }
}

批量插入

插入的action为index。

POST example/docs/_bulk
{"index": {"_id": 1}}
{"id":1, "name": "admin", "counter":"10", "tags":["red", "black"]}
{"index": {"_id": 2}}
{"id":2, "name": "张三", "counter":"20", "tags":["green", "purple"]}
{"index": {"_id": 3}}
{"id":3, "name": "李四", "counter":"30", "tags":["red", "blue"]}
{"index": {"_id": 4}}
{"id":4, "name": "tom", "counter":"40", "tags":["orange"]}

批量修改

修改的action为update。

POST example/docs/_bulk
{"update": {"_id": 1}}
{"doc": {"id":1, "name": "admin-02", "counter":"11"}}
{"update": {"_id": 2}}
{"script":{"lang":"painless","source":"ctx._source.counter += params.num","params": {"num":2}}}
{"update":{"_id": 3}}
{"doc": {"name": "test3333name", "counter": 999}}
{"update":{"_id": 4}}
{"doc": {"name": "test444name", "counter": 888},  "doc_as_upsert" : true}

批量删除

修改的action为delete。

POST example/docs/_bulk
{"delete": {"_id": 1}}
{"delete": {"_id": 2}}
{"delete": {"_id": 3}}
{"delete": {"_id": 4}}

批量的混合操作

不过一般不推荐这种使用,项目中也用的极少。

POST _bulk
{ "index" : { "_index" : "example", "_type" : "docs", "_id" : "1" } }
{ "name" : "value11111" }
{ "delete" : { "_index" : "example", "_type" : "docs", "_id" : "2" } }
{ "create" : { "_index" : "example", "_type" : "docs", "_id" : "3" } }
{ "tags" : "value333" }
{ "update" : {"_id" : "4", "_type" : "docs", "_index" : "example"} }
{ "doc" : {"name" : "混合444"} 

并发控制(高级部分)

处理冲突

https://www.elastic.co/guide/cn/elasticsearch/guide/current/version-control.html

乐观并发控制

https://www.elastic.co/guide/cn/elasticsearch/guide/current/optimistic-concurrency-control.html

部分文档更新

https://www.elastic.co/guide/cn/elasticsearch/guide/current/partial-updates.html

更新文档

es提供了put 和 update两个api进行文档更新。

update较重,是从原文档生出新文档,再删除原文档,索引新文档。

https://www.elastic.co/guide/cn/elasticsearch/guide/current/update-doc.html

一切都是json

Mysql与es中名词的对应关系

  • Index 对应 MySQL 中的 Database
  • Type 对应 MySQL 中的 Table
  • Document 对应 MySQL 中表的记录
  • field对应MySQL中表的column

es在后台将每个索引划分成多个分片,分片可以在集群中不同服务器之间进行转移。

standalone模式的es,一个人就是一个集群,其集群名字默认为elasticSearch。

es文档的特点(Document的特点)

  1. document同时包含key:value。
  2. document可以嵌套包含另一个文档。
  3. document没有固定的字段,可以动态新增或忽略字段。

字段的特点(fields的特点)

es会特别关注并存储每个field的类型,这个类型被称为映射类型。

未归类

一个集群至少一个节点,一个节点是一个es进程。

节点可以有多个默认索引,创建新索引(库)默认产生10个分片,5个主分片(primary shard)5个副本分片(replica shard)。

一个es索引代表一个es的库,库里面包含多个lucense索引文件,每个文件包含<标签,含有标签的document>

一定要保证es的maven相关包和当前使用的es版本保持一致。

集群的健康状况为 yellow 则表示全部  分片都正常运行(集群可以正常服务所有请求),但是 副本分片没有全部处在正常状态。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值