天天看点

ElasticSearch - 批量操作 bulk

  • bulk

    允许在一个请求中进行多个操作(create、index、update、delete),也就是可以在一次请求裡做很多事情
    • 也由于这个关系,因此bulk的请求体和其他请求的格式会有点不同
  • bulk的请求模板
    • 分成action、metadata和doc三部份
      • action : 必须是以下4种选项之一
        • index

          (最常用) : 如果文档不存在就创建他,如果文档存在就更新他
        • create

          : 如果文档不存在就创建他,但如果文档存在就返回错误
          • 使用时一定要在metadata设置

            _id

            值,他才能去判断这个文档是否存在
        • update

          : 更新一个文档,如果文档不存在就返回错误
          • 使用时也要给

            _id

            值,且后面文档的格式和其他人不一样
        • delete

          : 删除一个文档,如果要删除的文档id不存在,就返回错误
          • 使用时也必须在metadata中设置文档

            _id

            ,且后面不能带一个doc,因为没意义,他是用

            _id

            去删除文档的
      • metadata : 设置这个文档的metadata,像是

        _id

        _index

        _type

        ...
      • doc : 就是一般的文档格式
      POST 127.0.0.1/mytest/doc/_bulk
      { action : { metadata } }
      { doc }
      { action : { metadata } }
      { doc }
      ....
                 
  • 具体实例
    • bulk请求
      POST 127.0.0.1/mytest/doc/_bulk
      //创建一笔数据
      { "create" : { "_id": 1 } }
      { "color": "create black" }
      //创建一笔数据,因为id=1的文档已经存在,所以会创建失败
      { "create" : { "_id": 1 } }
      { "color": "create black2" }
      //索引一笔数据
      { "index" : { "_id": 2 } } 
      { "color": "index red" }
      //索引一笔数据,但是index可以创建也可以更新,所以执行成功
      { "index" : { "_id": 2 } } 
      { "color": "index red2" }
      //索引一笔数据,不一定要设置id(index又能创建又能更新又不用设id,超好用)
      { "index": {} } 
      { "color": "index blue" } 
      //删除一笔文档,注意delete后面不接一个doc
      { "delete" : { "_id": "2" } } 
      //找不到此id的文档,删除失败
      { "delete" : { "_id": "2" } } 
      //更新一笔文档,注意doc格式不太一样
      { "update" : { "_id": 1 } } 
      { "doc": { "color": "update green"} }
      //更新一笔文档,但因为此id的文档不存在,所以更新失败
      { "update" : { "_id": 100 } } 
      { "doc": { "color": "update green2"} }
                 
  • bulk的返回结果
    • 因为在bulk中,每个action的执行结果都是独立的,所以有几个action,就会有几个返回结果,返回结果如下
      • 最上面会有一个

        errors

        ,表示这一次bulk请求中,是否有action出错了
        • 因此写代码时可以先检查

          errors

          这个值,如果是false,表示这次bulk请求全部通过,就不用再一一去检查是否有action出错,但如果是true,则必须去

          items

          一个一个检查到底是哪个action出错了
      • items

        是一个数组,裡面则放著每个action对应的结果,上面的请求执行了9个action,所以返回结果的items就会有9个
        • 返回结果会依照action的顺序排好,因此

          items

          的第一个结果就是请求时第一个action的执行结果
      {
          "took": 22,
          "errors": true,
          "items": [
              {
                  "create": {
                      "_index": "mytest",
                      "_type": "doc",
                      "_id": "1",
                      "status": 201
                  }
              },
              {
                  "create": {
                      "_index": "mytest",
                      "_type": "doc",
                      "_id": "1",
                      "status": 409,
                      "error": {
                          "type": "version_conflict_engine_exception",
                          "reason": "[doc][1]: version conflict, document already exists (current version [1])",
                          "index_uuid": "hc_2I5efRMK3_RUC0HJGew",
                          "shard": "3",
                          "index": "mytest"
                      }
                  }
              },
              {
                  "index": {
                      "_index": "mytest",
                      "_type": "doc",
                      "_id": "2",
                      "status": 201
                  }
              },
              {
                  "index": {
                      "_index": "mytest",
                      "_type": "doc",
                      "_id": "2",
                      "status": 200
                  }
              }
              ... 5 RESULTS REMOVED ...
          ]
      }
                 
  • 使用bulk要注意的地方
    • 如果使用

      127.0.0.1/_bulk

      ,那麽就是在整个ES的范围中插入数据,因此在metadata中要指定插入的index和type,优点是可以一次插入多笔数据到不同的索引
      • 而如果使用

        127.0.0.1/mytest/doc/_bulk

        ,就不用在metadata再次指定要插入的index和type,可以想像成是

        _bulk

        API帮我们自动填好了metadata的

        _index

        _type

        ,很方便
    • 还有因为bulk和其他请求的格式不同,或是说基本上他已经不是正常的json格式了,所以在使用bulk时,HTTP header要使用

      application/x-ndjson

      • 而且每一行的结尾,都要使用

        \n

        ,如果是一般在postman写请求不会有问题,但是如果是使用

        curl

        来发送请求,就要使用

        --data-binary

        ,才会使每一句的结尾都是

        \n

继续阅读