数据的输入和输出

数据的输入和输出

  1. es是分布式的文档存储,它能够存储和检索复杂的数据结构序列化成json文档
    一旦一个文档被存储到es中,他就可以被集群中任意节点检索到
  2. 在es中,每个字段的所有数据默认都是被索引的,即每个字段都有为了快速检索而设置的专用倒排索引,
    他不像其它多数数据库,他能在同一个查询中使用所有这些倒排索引,并以惊人的速度返回结果

什么是文档

  1. 通常情况下我们使用的术语对象和文档是可以相互替换的
  2. 在es中,文档有着特定的含义,它是指最顶层或者根对象,这个根对象被序列化成json并存储到es中
    指定了唯一ID

文档元数据

  1. _index:
    一个索引应该是因共同的特征分配到一起的文档的集合。
    实际上,在es中,我们的数据是被存储和索引在分片中,而一个索引仅仅是逻辑上的命名空间
    这个命名空间由一个或多个分片组成,我们只需要知道文档在哪个索引内,es能帮我们处理所有内部分片细节
  • 索引名规范:索引名必须小写,不能以下划线开头,不能包含逗号
  1. _type:
    es8.1中已经完全废弃了,不在讲解
  2. _id:
    _id是字符串,当它和_index和_doc组合就可以唯一确定es中的一个文档,
    创建文档时,可以自己提供_id,也可以让es自动生成

索引文档

  1. 一个文档的 _index、_doc、_id唯一标识一个文档
    自动生成的 ID 是 URL-safe、 基于 Base64 编码且长度为20个字符的 GUID 字符串。
    这些 GUID 字符串由可修改的 FlakeID 模式生成,这种模式允许多个节点并行生成唯一 ID ,
    且互相之间的冲突概率几乎为零

取回一个文档

  1. GET请求的响应体包含{"found": true},标识找到了,如果请求一个不存在的文档Id仍会返回json响应体
    只不过found会是false

  2. 返回文档的一部分
    GET /website/_doc/123?_source=title,text

  3. 只想要_source数据,不需要元数据
    GET /website/_source/123/

  4. 只想要_source中的部分字段,元数据也不要
    GET /website/_source/123/?_source=title,date

{
    "title": "My first blog entry",
    "date": "2014/01/01"
}

检索文档是否存在

  1. 检查一个文档是否存在使用HEAD方法即可
    /website/_doc/123
    /website/_source/123

更新整个文档

  1. 跟创建文档一致,只不过post方法改为put方法即可,必须传递要修改的文档_id
  2. 所谓的更新其实是把旧的文档标记为已删除,然后创建一个新的文档,当继续索引更多数据时,
    es会在后台将这些已标记删除的文档清除掉

创建新文档

  1. 当我们索引一个文档,怎么确认我们正在创建一个全新的文档,而不是覆盖现有的呢
    确保创建一个新文档的最简单办法就是post请求,让api自动生成_id
  2. 然后如果已经有了自己的_id,那么我们必须告诉es,只有相同_index、_id不存在时才接收我们的索引请求
    使用op_type查询字符串参数
    POST /website/_doc/124?op_type=create
    这样的话,website索引中不存在124id时才会创建成功status:201,否则抛出异常status:409

删除文档

  1. DELETE /website/_doc/125
    删除成功,status:200, "result": "deleted",
    删除失败:status:404, "result": "not_found"

  2. 即使文档不存在(result:not_found),_version值仍会增加,这是es内部记录本的一部分
    用来确保这些改变在跨多节点时以正确的顺序执行

  3. 删除文档不会立即从磁盘中删除,而是将文档标记为已删除状态,随着后期es不断索引数据,在后台清除以标记删除的文档

乐观并发控制

  1. es是分布式的,当文档创建、更新或删除时,新版本中的文档必须复制到其它节点
    es也是异步和并发的,这意味着这些复制请求被并行发送,并且到达目的地时顺序是乱的
    es需要一种方法确保文档的旧版本不会覆盖新版本

  2. 前面我们说过每一个文档都有一个_version版本号,当文档被修改时版本号递增,
    es通过_version保证文档被正确执行,如果旧版本的文档在新版本之后到达,它可以被简单的忽略

  3. 乐观并发控制
    PUT /website/_doc/1?if_seq_no=15&if_primary_term=1

{
  "title": "My first blog entry",
  "text":  "Starting to get the hang of this..."
}
  1. 通过外部系统使用版本控制
  • 先查询出_seq_no和_primary_term
    GET /website/_doc/1
  • 然后更新带上获取的这两个参数
    PUT /website/_doc/1?if_seq_no=27&if_primary_term=1
{
  "title": "My first blog entry",
  "text":  "Starting to get the hang of this..."
}

文档的部分更新

新版本暂时没找到解决方法...

取回多个文档

  1. Elasticsearch 的速度已经很快了,但甚至能更快。 将多个请求合并成一个,避免单独处理每个请求花费的网络延时和开销。
    如果你需要从 Elasticsearch 检索很多文档,那么使用 multi-get 或者 mget API 来将这些检索请求放在一个请求中,
    将比逐个文档请求更快地检索到全部文档。

  2. mget API要求有一个docs数组作为参数,每个元素包含需要检索文档的元数据,包括_index、_id
    如果想检索一个或者多个特定的字段,可以通过_source参数来指定这些字段的名字
    GET /_mget

{
    "docs": [
        {
            "_index": "website",
            "_id": 1
        },
        {
            "_index": "website",
            "_id": 123,
            "_source": ["title", "date"]
        }
    ]
}

如果想检索的数据在相同的_index中,则可以在URL中指定默认的/_index
同时仍然可以通过单独请求覆盖这些值
GET /website/_mget

{
    "docs": [
        {
            "_id": 1
        },
        {
            "_id": 123,
            "_source": ["title", "date"]
        },
        {
            "_index": "accounts",
            "_id": 1
        }
    ]
}

事实上,如果所有文档的_index都是相同的,可以只传递一个ids数组,而不是整个docs数组
GET /website/_mget

{
    "ids": [1, 2, 3, 123]
}

找到的返回文档,同时found返回true;找不到的found返回false
事实上未找到的文档并不妨碍被找到的文档,每个文档都是单独检索和报告的,
即使文档都没有找到,状态码仍然是200,因为_mget请求本身已经成功执行,
为了确定某个文档是否成功找到,可以查看found标记

参考文档

posted @ 2022-04-12 16:15  专职  阅读(50)  评论(0编辑  收藏  举报