zoukankan      html  css  js  c++  java
  • Elasticserch学习之数据

    一、索引

    1、使用自己的ID

    例如我们的索引叫做“website”,类型叫做“blog”,我们选择的ID是“123”,那么这个索引请求就像这样:

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

    2、自增ID

    URL现在只包含_index_type两个字段:

    POST /website/blog/
    {
      "title": "My second blog entry",
      "text":  "Still trying this out...",
      "date":  "2014/01/01"
    }

    二、获取

    1、检索文档

    GET /website/blog/123?pretty

    pretty

    在任意的查询字符串中增加 pretty 参数,类似于上面的例子。会让Elasticsearch美化输出(pretty-print)JSON响应以便更加容易阅读。_source字段不会被美化,它的样子与我们输入的一致。

    2、检索文档的一部分

    GET /website/blog/123?_source=title,text

    _source字段现在只包含我们请求的字段,而且过滤了date字段:

    {
      "_index" :   "website",
      "_type" :    "blog",
      "_id" :      "123",
      "_version" : 1,
      "exists" :   true,
      "_source" : {
          "title": "My first blog entry" ,
          "text":  "Just trying this out..."
      }
    }

    或者你只想得到_source字段而不要其他的元数据,你可以这样请求:

    GET /website/blog/123/_source

    它仅仅返回:

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

    三、检查文档是否存在

    HEAD /website/blog/123

    Elasticsearch将会返回 200 OK 状态如果你的文档存在:

    200 - OK

    如果不存在返回 404 Not Found:

    HEAD /website/blog/124
    404 - Not Found

    当然,这只表示你在查询的那一刻文档不存在,但并不表示几毫秒后依旧不存在。另一个进程在这期间可能创建新文档。

    四、更新整个文档

    PUT /website/blog/123
    {
      "title": "My first blog entry",
      "text":  "I am starting to get the hang of this...",
      "date":  "2014/01/02"
    }

    在响应中,我们可以看到Elasticsearch把_version增加了。

    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "123",
      "_version" : 3,
      "result" : "updated",
      "_shards" : {
        "total" : 2,
        "successful" : 1,
        "failed" : 0
      },
      "_seq_no" : 3,
      "_primary_term" : 1
    }

    在内部,Elasticsearch已经标记旧文档为删除并添加了一个完整的新文档。旧版本文档不会立即消失,但你也不能去访问它。Elasticsearch会在你继续索引更多数据时清理被删除的文档。

    五、创建一个新文档

    1、最简单的方式是使用POST方法让Elasticsearch自动生成唯一 _id

    POST /website/blog/
    { 
      "title": "My first blog entry",
      "text":  "I am starting to get the hang of this...",
      "date":  "2014/01/02"
    }

    2、使用op_type查询参数

    PUT /website/blog/125?op_type=create
    {
      "title": "My first blog entry",
      "text":  "I am starting to get the hang of this...",
      "date":  "2014/01/02"
    }

    3、在URL后加/_create做为端点

    PUT /website/blog/124/_create
    {
      "title": "My first blog entry",
      "text":  "I am starting to get the hang of this...",
      "date":  "2014/01/02"
    }

    六、删除文档

    删除文档的语法模式与之前基本一致,只不过要使用DELETE方法:

    DELETE /website/blog/124

    如果文档被找到,Elasticsearch将返回200 OK状态码和以下响应体。注意_version数字已经增加了。

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

    如果文档未找到,我们将得到一个404 Not Found状态码,响应体是这样的:

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

    尽管文档不存在——"found"的值是false——_version依旧增加了。这是内部记录的一部分,它确保在多节点间不同操作可以有正确的顺序。

    七、版本控制

    例如,创建一个包含外部版本号5的新博客,我们可以这样做:

    PUT /website/blog/2?version=5&version_type=external
    {
      "title": "My first external blog entry",
      "text":  "Starting to get the hang of this..."
    }

    在响应中,我们能看到当前的_version号码是5

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

    现在我们更新这个文档,指定一个新version号码为10

    PUT /website/blog/2?version=10&version_type=external
    {
      "title": "My first external blog entry",
      "text":  "This is a piece of cake..."
    }

    请求成功:

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

    八、局部更新

    示例:为博客添加一个tags字段和一个views字段。

    POST /website/blog/1/_update
    {
       "doc" : {
          "tags" : [ "testing" ],
          "views": 0
       }
    }

    请求成功:

    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "1",
      "_version" : 3,
      "result" : "updated",
      "_shards" : {
        "total" : 2,
        "successful" : 1,
        "failed" : 0
      },
      "_seq_no" : 6,
      "_primary_term" : 1
    }

    检索文档文档显示被更新的_source字段:

    {
            "_index" : "website",
            "_type" : "blog",
            "_id" : "1",
            "_score" : 1.0,
            "_source" : {
              "title" : "My first blog entry",
              "text" : "Starting to get the hang of this...",
              "views" : 0,
              "tags" : [
                "testing"
              ]
            }
      }

    使用脚本局部更新

    使用Groovy脚本:

    默认的脚本语言是Groovy,一个快速且功能丰富的脚本语言,语法类似于Javascript。它在一个沙盒(sandbox)中运行,以防止恶意用户毁坏Elasticsearch或攻击服务器。

    脚本能够使用update API改变_source字段的内容,它在脚本内部以ctx._source表示。

    示例:使用脚本增加博客的views数量。

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

    九、Mget

    1、检索多个文档

    POST /_mget
    {
       "docs" : [
          {
             "_index" : "website",
             "_type" :  "blog",
             "_id" :    2
          },
          {
             "_index" : "website",
             "_type" :  "pageviews",
             "_id" :    123,
             "_source": "views"
          }
       ]
    }

    如果你想检索的文档在同一个_index中(甚至在同一个_type中),你就可以在URL中定义一个默认的/_index或者/_index/_type

    POST /website/blog/_mget
    {
       "docs" : [
          { "_id" : 2 },
          { "_type" : "pageviews", "_id" :   1 }
       ]
    }

    事实上,如果所有文档具有相同_index_type,你可以通过简单的ids数组来代替完整的docs数组:

    POST /website/blog/_mget
    {
       "ids" : [ "2", "1" ]
    }

    注意到我们请求的第二个文档并不存在。我们定义了类型为blog,但是ID为1的文档类型为pageviews。这个不存在的文档会在响应体中被告知。

    {
      "docs" : [
        {
          "_index" :   "website",
          "_type" :    "blog",
          "_id" :      "2",
          "_version" : 10,
          "found" :    true,
          "_source" : {
            "title":   "My first external blog entry",
            "text":    "This is a piece of cake..."
          }
        },
        {
          "_index" :   "website",
          "_type" :    "blog",
          "_id" :      "1",
          "found" :    false  <1>
        }
      ]
    }
    • <1> 这个文档不存在

    事实上第二个文档不存在并不影响第一个文档的检索。每个文档的检索和报告都是独立的。

    十、更新时的批量操作

    就像 mget 允许我们一次性检索多个文档一样,bulk API允许我们使用单一请求来实现多个文档的 createindexupdatedelete。这对索引类似于日志活动这样的数据流非常有用,它们可以以成百上千的数据为一个批次按序进行索引。

    bulk请求体如下:

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

     这种格式类似于用" "符号连接起来的一行一行的JSON文档流(stream)。两个重要的点需要注意:

    • 每行必须以" "符号结尾,包括最后一行。这些都是作为每行有效的分离而做的标记。

    • 每一行的数据不能包含未被转义的换行符,它们会干扰分析——这意味着JSON不能被美化打印。

    action/metadata 这一行定义了文档行为(what action)发生在哪个文档(which document)之上。

    行为(action)必须是以下几种:

    行为解释
    create 当文档不存在时创建之。详见《创建文档》
    index 创建新文档或替换已有文档。见《索引文档》和《更新文档》
    update 局部更新文档。见《局部更新》
    delete 删除一个文档。见《删除文档》

    在索引、创建、更新或删除时必须指定文档的_index_type_id这些元数据(metadata)。

    例如删除请求看起来像这样:

    { "delete": { "_index": "website", "_type": "blog", "_id": "123" }}

    这些还被 update 操作所必需,而且请求体的组成应该与update API(docupsertscript等等)一致。删除操作不需要请求体(request body)。

    { "create":  { "_index": "website", "_type": "blog", "_id": "123" }}
    { "title":    "My first blog post" }

    如果没有定义_id,ID将会被自动创建:

    { "index": { "_index": "website", "_type": "blog" }}
    { "title":    "My second blog post" }

    为了将这些放在一起,bulk请求表单是这样的:

    POST /_bulk
    { "delete": { "_index": "website", "_type": "blog", "_id": "123" }} <1>
    { "create": { "_index": "website", "_type": "blog", "_id": "123" }}
    { "title":    "My first blog post" }
    { "index":  { "_index": "website", "_type": "blog" }}
    { "title":    "My second blog post" }
    { "update": { "_index": "website", "_type": "blog", "_id": "123", "_retry_on_conflict" : 3} }
    { "doc" : {"title" : "My updated blog post"} } <2>
    • <1> 注意delete行为(action)没有请求体,它紧接着另一个行为(action)。
    • <2> 记得最后一个换行符。

    Elasticsearch响应包含一个items数组,它罗列了每一个请求的结果,结果的顺序与我们请求的顺序相同:

    {
      "took" : 103,
      "errors" : false,   <1>
      "items" : [
        {
          "delete" : {
            "_index" : "website",
            "_type" : "blog",
            "_id" : "123",
            "_version" : 5,
            "result" : "deleted",
            "_shards" : {
              "total" : 2,
              "successful" : 1,
              "failed" : 0
            },
            "_seq_no" : 5,
            "_primary_term" : 1,
            "status" : 200
          }
        },
        {
          "create" : {
            "_index" : "website",
            "_type" : "blog",
            "_id" : "123",
            "_version" : 6,
            "result" : "created",
            "_shards" : {
              "total" : 2,
              "successful" : 1,
              "failed" : 0
            },
            "_seq_no" : 6,
            "_primary_term" : 1,
            "status" : 201
          }
        },
        {
          "index" : {
            "_index" : "website",
            "_type" : "blog",
            "_id" : "cP66bGkBUi3i0pMApm5N",
            "_version" : 1,
            "result" : "created",
            "_shards" : {
              "total" : 2,
              "successful" : 1,
              "failed" : 0
            },
            "_seq_no" : 8,
            "_primary_term" : 1,
            "status" : 201
          }
        },
        {
          "update" : {
            "_index" : "website",
            "_type" : "blog",
            "_id" : "123",
            "_version" : 7,
            "result" : "updated",
            "_shards" : {
              "total" : 2,
              "successful" : 1,
              "failed" : 0
            },
            "_seq_no" : 7,
            "_primary_term" : 1,
            "status" : 200
          }
        }
      ]
    }
    • <1> 所有子请求都成功完成。

    每个子请求都被独立的执行,所以一个子请求的错误并不影响其它请求。如果任何一个请求失败,顶层的error标记将被设置为true,然后错误的细节将在相应的请求中被报告:

    POST /_bulk
    { "create": { "_index": "website", "_type": "blog", "_id": "123" }}
    { "title":    "Cannot create - it already exists" }
    { "index":  { "_index": "website", "_type": "blog", "_id": "123" }}
    { "title":    "But we can update it" }

    响应中我们将看到create文档123失败了,因为文档已经存在,但是后来的在123上执行的index请求成功了:

    {
      "took" : 42,
      "errors" : true,  <1>
      "items" : [
        {
          "create" : {
            "_index" : "website",
            "_type" : "blog",
            "_id" : "123",
            "status" : 409,  <2>
            "error" : {
              "type" : "version_conflict_engine_exception",  <3>
              "reason" : "[blog][123]: version conflict, document already exists (current version [7])",
              "index_uuid" : "Uc01DQRhSqq_REs9HsSYPA",
              "shard" : "0",
              "index" : "website"
            }
          }
        },
        {
          "index" : {
            "_index" : "website",
            "_type" : "blog",
            "_id" : "123",
            "_version" : 8,
            "result" : "updated",
            "_shards" : {
              "total" : 2,
              "successful" : 1,
              "failed" : 0
            },
            "_seq_no" : 8,
            "_primary_term" : 1,
            "status" : 200  <4>
          }
        }
      ]
    }
    • <1> 一个或多个请求失败。
    • <2> 这个请求的HTTP状态码被报告为409 CONFLICT
    • <3> 错误消息说明了什么请求错误。
    • <4> 第二个请求成功了,状态码是200 OK

    这些说明 bulk 请求不是原子操作——它们不能实现事务。每个请求操作时分开的,所以每个请求的成功与否不干扰其它操作。

    不要重复

    你可能在同一个index下的同一个type里批量索引日志数据。为每个文档指定相同的元数据是多余的。就像mget API,bulk请求也可以在URL中使用/_index/_index/_type:

    POST /website/_bulk
    { "index": { "_type": "log" }}
    { "event": "User logged in" }

    你依旧可以覆盖元数据行的_index_type,在没有覆盖时它会使用URL中的值作为默认值:

    POST /website/log/_bulk
    { "index": {}}
    { "event": "User logged in" }
    { "index": { "_type": "blog" }}
    { "title": "Overriding the default type" }
  • 相关阅读:
    原型链的树形结构
    粗略讲一讲js的代码执行机制
    30天前端打卡整理记录
    简单模拟Vue的数据代理功能
    JavaScript语言精粹读后记录
    JavaScript巧用对象的引用解决三级联动
    es6新了解
    记录小程序开发的n个坑
    比拼人品-拼手气红包的JavaScript实现方式.
    一诺千金:微信小程序的wx.request 与Promise的结合使用
  • 原文地址:https://www.cnblogs.com/mentiantian/p/10512945.html
Copyright © 2011-2022 走看看