es基础入门之数据输入和输出

  Elastcisearch 是分布式的 文档 存储。它能存储和检索复杂的数据结构—​序列化成为JSON文档—​以 实时 的方式。 换句话说,一旦一个文档被存储在 Elasticsearch 中,它就是可以被集群中的任意节点检索到。
  当然,我们不仅要存储数据,我们一定还需要查询它,成批且快速的查询它们。 尽管现存的 NoSQL 解决方案允许我们以文档的形式存储对象,但是他们仍旧需要我们思考如何查询我们的数据,以及确定哪些字段需要被索引以加快数据检索。

  倒排索引源于实际应用中需要根据属性的值来查找记录。这种索引表中的每一项都包括一个属性值和具有该属性值的各记录的地址。由于不是由记录来确定属性值,而是由属性值来确定记录的位置,因而称为倒排索引(inverted index)。带有倒排索引的文件我们称为倒排索引文件,简称倒排文件(inverted file)。

  在 Elasticsearch 中, 每个字段的所有数据都是默认被索引的 。 即每个字段都有为了快速检索设置的专用倒排索引。而且,不像其他多数的数据库,它能在同一个查询中使用所有这些倒排索引,并以惊人的速度返回结果。

(1)索引文档
  新建document时,可以指定id,也可以使用默认的id。如果指定了id,则不会在生成默认的id。自动生成的 ID 是 URL-safe、 基于 Base64 编码且长度为20个字符的 GUID 字符串。 这些 GUID 字符串由可修改的 FlakeID 模式生成,这种模式允许多个节点并行生成唯一 ID ,且互相之间的冲突概率几乎为零。

  a.使用指定的id

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

  b.使用默认的id

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

(2)检索文档

GET /website/blog/123?pretty

我们可以使用_source参数定制返回结果字段。例如:

GET /website/blog/123?_source=filed1

(3)更新文档

  在 Elasticsearch 中文档是不可改变 的,不能修改它们。相反,如果想要更新现有的文档,需要重建索引或者进行替换。

a.使用全量替换

PUT /nidex/type/id
{
  "new filed": "new value"
}

  1)替换语法与创建文档是一样的,如果document id不存在,那么就是创建;如果document id已经存在,那么就是全量替换操作,替换document的json串内容
  2)document是不可变的,如果要修改document的内容,第一种方式就是全量替换,直接对document重新建立索引,替换里面所有的内容,第二种方式就是通过post修改某一个字段。
  3)无论是替换还是删除,都不会不会直接物理删除,只会将其标记为deleted,es会在适当的时机在后台自动删除标记为deleted的document。

b. partial update

POST /index/type/id/_update
{
   "doc" : {
      "filed": value
   }
}

  我们也介绍过文档是不可变的:他们不能被修改,只能被替换。 从外部来看,我们在一个文档的某个位置进行部分更新,但实际上,是接收更新请求doc 的参数, 并与根据id进行检索出来的文档进行合并。对象被合并到一起,覆盖现有的字段,增加新的字段。重新进行全量覆盖。
(3)删除文档

DELETE /index/type/id

  正如已经在[ (2)更新文档 ]中提到的,删除文档不会立即将文档从磁盘中删除,只是将文档标记为已删除状态。随着你不断的索引更多的数据,Elasticsearch 将会在后台清理标记为已删除的文档。
(4)并发冲突
  Elasticsearch 是分布式的。当文档创建、更新或删除时, 新版本的文档必须复制到集群中的其他节点。Elasticsearch 也是异步和并发的,这意味着这些复制请求被并行发送,也许这些请求到达目的地时,顺序有可能错乱,导致出现数据不一致的情况。
  比如更新库存时,此时库存数量为100,此时有两个请求同时想要库存减一,正确的结果应该是98, 但此时复制请求同时到达其他节点,导致节点内的数据变成99, 出现了数据不一致的情况。
  es是通过乐观并发控制进行解决并发冲突问题的,之前我们说过,无论是更新还是删除,es都不会真正的将旧文档从节点中删除,而是将他们的_version +1,如果是删除则标记为_delete状态。上例进行更新库存时,会通过CAS进行对_version的检查,如果他所获取的文档的_version和节点内部的_version一致,才会进行更新。
  可以通过以下案例进行测试.

1. 新增一个文档,此时_version为1
PUT /website/blog/1/_create
{
  "title": "My first blog entry",
  "text":  "Just trying this out..."
}
2. 可以给定version参数,此时和节点内部的version一致,所以会更新成功
PUT /website/blog/1?version=1
{
  "title": "My first blog entry",
  "text":  "Starting to get the hang of this..."
}

  一个常见的设置是使用其它数据库作为主要的数据存储,使用 Elasticsearch 做数据检索, 这意味着主数据库的所有更改发生时都需要被复制到 Elasticsearch ,如果多个进程负责这一数据同步,你可能遇到类似于之前描述的并发问题。也就是更改不依赖于原值,你可以通过外部系统使用版本控制,此时应该增加参数version_type=external。
  默认只有当你提供的version与es中的_version一致的时候,才可以进行修改,不一样就报错;当version_type=external的时候,只要你提供的version不小于es中的_version,就能完成修改。

(5)检索多个文档
1)一条一条的查询

GET /index/type/1
GET /indextype/2

2)mget批量操作

GET /_mget
{
   "docs" : [
      {
         "_index" : "test_index",
         "_type" :  "test_type",
         "_id" :    1
      },
      {
         "_index" : "test_index",
         "_type" :  "test_type",
         "_id" :    2
      }
   ]
}

3)如果查询的document是一个index下的不同type种的话

GET /test_index/_mget
{
   "docs" : [
      {
         "_type" :  "test_type",
         "_id" :    1
      },
      {
         "_type" :  "test_type",
         "_id" :    2
      }
   ]
}

4)如果查询的数据都在同一个index下的同一个type下,

GET /test_index/test_type/_mget
{
   "ids": [1, 2]
}

  一般来说,在进行查询的时候,如果一次性要查询多条数据的话,那么一定要用batch批量操作的api尽可能减少网络开销次数,可能可以将性能提升数倍,甚至数十倍。
(6) 批量操作

POST /_bulk
{"action": {"metadata"}}
{"data"}

action:
1)delete:删除一个文档,只要1个json串就可以了。
2)create:PUT /index/type/id/_create,强制创建。
3)index:普通的put操作,可以是创建文档,也可以是全量替换文档。
4)update:执行的partial update操作。
比如

POST /_bulk
{ "delete": { "_index": "test_index", "_type": "test_type", "_id": "3" }} 
{ "create": { "_index": "test_index", "_type": "test_type", "_id": "12" }}
{ "test_field":    "test12" }
{ "index":  { "_index": "test_index", "_type": "test_type", "_id": "2" }}
{ "test_field":    "replaced test2" }
{ "update": { "_index": "test_index", "_type": "test_type", "_id": "1", "_retry_on_conflict" : 3} }
{ "doc" : {"test_field2" : "bulk test1"} }

  1)每个子请求都是独立执行,因此某个子请求的失败不会对其他子请求的成功与否造成影响。
  2)不要重复的指定index和type,如果所有的批量操作都在一个index或者type内,可以和mget的api一样,在url路径中直接指定index和type。

POST index/type/_bulk
{"action": {"metadata"}}
{"data"}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容