2024-03-13
原文作者:吴声子夜歌 原文地址: https://blog.csdn.net/cold___play/article/details/104790273

增加文档

在Elasticsearch中如果有相同ID的文档存在,则更新此文档

示例:

    PUT /secisland/secilog/1
    {
      "collect_type":"syslog",
      "collect_date":"2016-01-11T09:32:12",
      "message":"xxxxx"
    }

返回:

    {
      "_index": "secisland",
      "_type": "secilog",
      "_id": "1",
      "_version": 1,
      "result": "created",
      "_shards": {
        "total": 2,//文档被创建的时候,在多少个分片中进行了操作,包括主分片和副本分片
        "successful": 1,//成功建立索引分片的数量,最少为1
        "failed": 0//失败建立索引的数量
      },
      "created": true
    }

自动创建索引

当创建文档的时候,如果索引不存在,则会自动创建该索引。自动创建的索引会自动映射每个字段的类型。

可以通过配置文件设置action.auto_create_index为false在所有节点的配置文件中禁用自动创建索引。自动映射的字段类型可以通过配置文件设置index.mapper.dynamec为false警用。

版本号

每个文档都有一个版本号,版本号的具体值放在创建索引的返回值中(_version)。通过版本号参数可以达到并发控制的效果。当在操作文档的过程中指定版本号,如果和版本号不一致的时候操作会被拒绝。

示例:

    PUT /secisland/secilog/1?version=2
    {
      "message": "yyyyyyy"
    }

返回:

    {
      "error": {
        "root_cause": [
          {
            "type": "version_conflict_engine_exception",
            "reason": "[secilog][1]: version conflict, current version [1] is different than the one provided [2]",
            "index_uuid": "lNWvsNq7QLuxpA-_Nq_RKQ",
            "shard": "3",
            "index": "secisland"
          }
        ],
        "type": "version_conflict_engine_exception",
        "reason": "[secilog][1]: version conflict, current version [1] is different than the one provided [2]",
        "index_uuid": "lNWvsNq7QLuxpA-_Nq_RKQ",
        "shard": "3",
        "index": "secisland"
      },
      "status": 409
    }

默认情况下对文档的操作版本号从1开始递增,包括修改文档和删除文档。

版本号也可以从外部获取,比如从数据库中获取,要启用此功能,version_type应设置为extternal,这个值必须是一个大于0小于9.2e+18的数字。当使用外部版本号来代替自动生成的版本号时,在操作文档的时候,系统通过对比参数中的版本号是否大于文档中的版本号来做判断,当参数中的版本号大于系统中的版本号,则执行此操作,并更新版本号。反之则拒绝操作。

操作类型

系统同时支持通过op_type=create参数强制命令执行创建操作,只有系统中不存在此文档的时候才会创建成功。如果不指定此操作类型,如果存在此文档,则会更新此文档。

示例:再次创建id存在的文档

    PUT /secisland/secilog/1?op_type=create
    {
      "collect_type":"syslog",
      "collect_date":"2016-01-11T09:32:12",
      "message":"zzzzz"
    }

返回:

    {
      "error": {
        "root_cause": [
          {
            "type": "version_conflict_engine_exception",
            "reason": "[secilog][1]: version conflict, document already exists (current version [1])",
            "index_uuid": "lNWvsNq7QLuxpA-_Nq_RKQ",
            "shard": "3",
            "index": "secisland"
          }
        ],
        "type": "version_conflict_engine_exception",
        "reason": "[secilog][1]: version conflict, document already exists (current version [1])",
        "index_uuid": "lNWvsNq7QLuxpA-_Nq_RKQ",
        "shard": "3",
        "index": "secisland"
      },
      "status": 409
    }

当不指定op_type=create时候,则更新此文档。

创建操作的另一个写法:

    PUT /secisland/secilog/1/_create

自动创建ID

当创建文档的时候,如果不指定ID,系统会自动创建ID。自动生成的ID是一个不会重复的随机数。使用GUID算法,可以保证在分布式环境下,不同节点同一时间创建的_id一定是不冲突的。

分片选择

默认情况下,分片的选择是通过ID的散列值进行控制。这个只可以通过router参数进行手动的控制。可以在每个操作的基础上直接通过哈希函数的值来指定分片的选择。

示例:

    POST /secisland/secilog/>routing=secisland

分片的选择是通过指定routing=secisland参数的哈希值来确定的。

其它说明

  • 分布式:索引操作主要是针对主节点的分片进行,当主节点完成索引操作后,如果有副本节点,则分发到副本中。
  • 一致性:为了防止当网络出现问题时写入不一致,系统只有在有效节点的数量大于一定数量的时候生效(总结点数/2+1),该值可以通过action.write_consistency参数进行修改。
  • 刷新:更新的时候可以指定refresh参数为true来立即刷新所有的副本,当refresh设置为true的时候,系统做了充分的优化,不会对系统产生任何影响,需要注意的是查询操作refresh参数没有任何的意义。
  • 空操作:当文档内容没有任何改变的时候,更新文档操作也会生效,具体体现在版本号会发生变化。如果不希望此情况发生,在更新的时候指定detect_noop为true。这个参数在创建索引的时候无效。
  • 超时:默认情况下系统的超时时间是1分钟。可以通过设置timeout修改超时的时间,例如timeout-5m,表示超时的时间是5分钟。

更新删除文档

更新操作从索引中获取文档,执行脚本,然后获得返回结果。它使用版本号来控制文档获取或者重建索引。

脚本开启功能

在config/elasticsearch.yml文件添加以下代码:

    script.inline:on
    script.indexed:on
    script.file:on

用脚本更新文档
示例:

    POST /secisland/secilog/1/_update?pretty
    {
      "script": {
        "source": "ctx._source.counter += count"
      }
    }
    POST /secisland/secilog/1/_update
    {
      "script": {
        "source": "ctx._source.tags.add(params.tag)",
        "params": {"tag": "xxx"}
      }
    }

在脚本中,除了_source外其它内置参数也可以使用,例如_index,_type,_version,_routing,_parent,_timestamp,_ttl等。

    POST /secisland/secilog/1/_update
    {
      "script": {
        "source":"ctx._source.newfield = 'newvalue'"
      }
    }

删除文档

    DELETE /secisland/secilog/1

查询文档

    GET /secisland/secilog/1

返回:

    {
      "_index": "secisland",
      "_type": "secilog",
      "_id": "1",
      "_version": 5,
      "found": true,
      "_source": {
        "counter": 3,
        "tags": [
          "red",
          "xxx"
        ],
        "newfield": "newvalue"
      }
    }

默认情况下,查询获得的数据接口是实时的,并且不受索引的刷新率影响,为了禁用实时性,可以将参数realtime设置为false,或全局设置action.get.realtime为false。

禁用_source

    GET /secisland/secilog/1?_source=false

返回:

    {
      "_index": "secisland",
      "_type": "secilog",
      "_id": "1",
      "_version": 5,
      "found": true
    }

获取source中的一部分内容

    GET /secisland/secilog/1?_source_include=counter

返回:

    {
      "_index": "secisland",
      "_type": "secilog",
      "_id": "1",
      "_version": 5,
      "found": true,
      "_source": {
        "counter": 3
      }
    }

当一个文档内容非常多的时候,用包含或者过滤可以减少很多的网络负担。如果有多个,可以用逗号分开,或者用*通配符。

    GET /secisland/secilog/1?_source_include=counter,tags

只获取文档内容:

    GET /secisland/secilog/1/_source

分片选择:
可以在查询的时候指定路由选择(routing),当路由不存在的时候,返回为空值.

    GET /secisland/secilog/1/?routing=secisland

查询参数:
通过参数控制,查询的时候可以指定查询是在主节点上查询还是在副本节点上查询,参数有:

  • _primary:在主节点上查询
  • _local:尽可能在本地节点上进行查询
  • refresh:可以设置为true,使之在搜索操作前刷新相关的分片保证可以即时查询到。(非常耗费资源,尽量不要设置)
    GET /secisland/secilog/1?_primary&refresh=true

多文档操作

多文档查询可以在同一个接口中查询多个文档,可以分别指定index、type、id来进行多个文档的查询。响应包括所有查询到的文档数组,每个元素在结构上类似单个文档查询。

    POST _mget
    {
      "docs":[
        {"_index":"secisland","_type":"secilog","_id":"1"},
        {"_index":"secisland","_type":"secilog","_id":"2"}
      ]
    }

返回:

    {
      "docs": [
        {
          "_index": "secisland",
          "_type": "secilog",
          "_id": "1",
          "_version": 5,
          "found": true,
          "_source": {
            "counter": 3,
            "tags": [
              "red",
              "xxx"
            ],
            "newfield": "newvalue"
          }
        },
        {
          "_index": "secisland",
          "_type": "secilog",
          "_id": "2",
          "found": false
        }
      ]
    }

在查询的时候,index、type可以在URL中直接填写。

    POST /secisland/_mget?
    {
    	"docs": [
    		{"_type":"secilog","_id":"1"},
    		{"_type":"secilog","_id":"2"}
    	]
    }

type参数说明:

在多文档查询中,_type允许为空,它设置为空或者_all的时候,系统会匹配第一个查询到的结果。如果不设置_type,当有许多文件有相同的_id的时候,系统最终得到的只有第一个匹配的文档。

块操作:

块操作可以在一个接口中处理文档的内容,包括创建、删除和修改文档。

示例:

    POST _bulk
    {"index":{"_index":"secisland","_type":"secilog","_id":"1"}}
    {"counter":"1"}
    {"index":{"_index":"secisland","_type":"secilog","_id":"2"}}
    {"counter":"2"}

返回:

    {
      "took": 3,
      "errors": false,
      "items": [
        {
          "index": {
            "_index": "secisland",
            "_type": "secilog",
            "_id": "1",
            "_version": 7,
            "result": "updated",
            "_shards": {
              "total": 2,
              "successful": 1,
              "failed": 0
            },
            "created": false,
            "status": 200
          }
        },
        {
          "index": {
            "_index": "secisland",
            "_type": "secilog",
            "_id": "2",
            "_version": 2,
            "result": "updated",
            "_shards": {
              "total": 2,
              "successful": 1,
              "failed": 0
            },
            "created": false,
            "status": 200
          }
        }
      ]
    }

和批量查询类似,/_bulk、/{index}/_bulk、{index}/{type}/_bulk这三种方式都尅执行,只需要在请求的参数中做出相应的对应。

阅读全文