Elasticsearch的基本操作(三)

244 阅读5分钟

添加索引

  • 索引(index)是存储数据的地方,实际上索引是一个指向一个或者多个分片的"逻辑命名空间"。
  • 一个分片(shard)是一个最小级别的"工作单元",它只是存储了索引中索引数据的一部分,除此之外一个shard就是一个Lucenes实例。分片在集群内是很重要的,在集群扩大或者缩小的时候,Elasticsearch将会自动爱你的节点间迁移分片,以便保持集群的平衡。
  • 复制分片只是主分片的一个副本,它可以防止硬件的故障导致的数据丢失,同时可以提供读请求,比如搜索或者从别的分片取回文档。主分片是在索引创建的时候就已经确定的,复制分片完全可以在后期调整。

现在我们可以创建一个名为blog的索引,给该索引分配3个主分片和一个副分片(每个主分片一个副分片)

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

此时我们在调用 GET /_cluster/health 可以得到如下的结果

根据结果可以得知集群的状态是yellow,就是主分片都是可以使用的,但是副分片不都可以使用。unassigned_shards的结果是5,表示有5个分片是没有被分配的,因为这些副分片没有被分配,就是无法使用备份主分片的数据,如果出现节点的故障就无法实现故障转移,所以这个集群的状态是yellow的。

故障转移

在单一节点上运行会存在单点故障,为了防止单点故障我们需要做的就是启动更多的节点,如果我们在集群里面拓展了节点,那么从节点就会分配在其他节点上。

这个集群最大可以拓展到六个节点。

文档

程序中大多数的实体或对象能够被序列化为包含键值对的JSON对象,键是自带你或者属性的名字,值可以是字符出阿伯,数字,不二类型,另外一个对象,值数组或者其他特殊类型。实际上,我们可以认为对象(object)和文档(document)是等价的。但是它们之间是有差别:对象是一个JSON结构体----类似与哈希,hashmao,字典或者关联数组,对象中可以包含其他对象。在ES中,翁当这个是有特殊含义的,它只要代表了顶层结构或者根对象(root object)序列化成的JSON数据(以唯一ID表示并存储Elasticsearch中)

文档字定义ID和自增id

字定义ID

PUT /{index}/{type}/{id} { "field":"value" ... }

自增ID

POST /{index}/{type} { "field":"value" ... }

##索引文档

GET /website/blog/123/_source

返回结果:

{
  "title" : "My first blog entry",
  "text" : "Just trying this out...",
  "date" : "2014/01/01"
}

删除索引

DELETE /website/blog/125

返回结果:

{
  "_index" : "website",
  "_type" : "blog",
  "_id" : "125",
  "_version" : 2,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 11,
  "_primary_term" : 1
}

在上面的结果可以返现_version增加了1,这个是ES内部记录的一部分,确保多节点间不同操作可以有正确的顺序。

冲突处理

为了处理并发出现的冲突问题可以使用一下两种方式

1.悲观并发控制 这个方式在关系型数据库中内广泛的使用,这种方式假设冲突会发生,为了解决冲突,就在读一行数据前锁定这行,然后确保值枷锁的那个线程可以修改这行数据

2.乐观并发控制

被Elasticsearch使用,这种方式假设冲突不发生,不需要区块访问,如果在读写过程发生变化,更新操作就会失败,此时我们可以在程序中决定在失败后如何解决冲突,实际上我们可以尝试更新,刷新数据或者直接反馈给用户.

文档局部更新

文档是不可变的,它们是不可以被更改的,只能被替换。update API必须遵循相同的规则。表面上看来,我们似乎是局部更新了文档的某个地方,内部却是检索-修改-重建索引的流程,这样减少了其他进程可能导致冲突的修改。

POST /website/blog/124/_update
{
  
  "doc":{
    "title":"this is test demo"
  }
  
}

更新和冲突

在更新的时候可能有其他人在索引和修改,导致冲突,但是出现冲突不要紧,我们需要做的就是在出现冲突的时候重试,这样我们就可以结局冲突带来的问题。

POST /website/blog/124/_update?retry_on_conflict=2
{
  #这里使用的是脚本修改
  "script":{
    "lang":"painless",
    "inline":"ctx._source.title=params.title",
     "params":{
    "title":"Stander title"
  }
  }
}

更新不存在的文档

在更新文档的时候,我们如果更新了一个不存在的文档,那么我们就会更新失败,但是我们可以做到如果没有就插入一条记录,有就更新,如下面的例子

POST /website/blog/1/_update
{
"script" : "ctx._source.views+=1",
"upsert": {
"views": 1
}
}

批量查询

GET /website/blog/_mget
{
  "docs":[
    {"_id":"1"},
    {"_id":"123"}
    ]
}

返回结果

{
  "docs" : [
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "1",
      "_version" : 2,
      "_seq_no" : 19,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "views" : 2
      }
    },
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "123",
      "_version" : 3,
      "_seq_no" : 6,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "title" : "My first blog entry",
        "text" : "I am starting to get the hang of this....",
        "date" : "2019/07/31"
      }
    }
  ]
}

更新是的批量操作

bulk API允许我们使用单一请求来实现多个文档的create,index,update或者delete.这个对索引列斯日志活动这样的数据六非常由于,他可以成败上千的数据作为一个批次按顺序进行索引。

bulk请求体如下,它有一点不同寻常:

{action:{metadata}}\n
{request body}\n
{action:{metadata}}\n
{request body}\n
...

1.这种格式就是使用换行符"\n"将JSON串连接起来,可以说"\n"是作为每一行的的分离标识

2.每一行不能包含换行符,他们会干扰分析

action有一下几种:

行为 解释
create 当文档不存在时创建
index 创建新文档或者替换已有文档
update 局部更新文档
delete 删除一个文档

例子:

#批量更新

POST /_bulk
{ "index" : { "_index" : "test", "_type" : "_doc", "_id" : "1" } }
{ "field1" : "value1" }
{ "delete" : { "_index" : "test", "_type" : "_doc", "_id" : "2" } }
{ "create" : { "_index" : "test", "_type" : "_doc", "_id" : "3" } }
{ "field1" : "value3" }
{ "update" : {"_id" : "1", "_type" : "_doc", "_index" : "test"} }
{ "doc" : {"field2" : "value2"} }