Elasticsearch CURD

作者: lookphp | 来源:发表于2017-11-22 17:46 被阅读81次

    使用

    接下来,我们看看如何建立索引、创建文档等,就好比在 MySQL 中进行诸如创建数据库,插入数据等操作。

    Index:创建与更新索引

    在ElasticSearch中,Index这一动作类比于CRUD中的Create与Update,当我们尝试为某个不存在的文档建立索引时,会自动根据其类似于ID创建新的文档,否则就会对原有的文档进行修改。

    ElasticSearch使用PUT请求来进行Index操作,你需要提供索引名称、类型名称以及可选的ID,格式规范为:http://localhost:9200///[]。其中索引名称可以是任意字符,如果ElasticSearch中并不存在该索引则会自动创建。

    添加文档
    下面,我们将创建一个存储电影信息的Document :

    • Index 的名称为movie
    • Type 的名称为adventure
    • Document 有两个字段: name和actors

    我们使用 Elasticsearch 提供的 RESTful API 来执行上述操作,如图所示:

    image.png
    • url表示一个资源,比如 /movie/adventure/1 就表示一个indexmovietypeadventureid1document
    • http 方法操作资源,如使用 GET 获取资源,使用 POST、PUT新增或更新资源,使用 DELETE 删除资源等

    向指定的/Index/Type 发送 PUT 请求,就可以在Index 里面新增一条记录。比如,向/movie/adventure发送请求,就可以新增电影记录。

    我们可以使用 curl 命令来执行上述操作:

    curl -XPUT "http://localhost:9200/movie/adventure/1" -d '
    {
        "name": "Life of Pi",
        "actors": ["Suraj" , "Irrfan"]
    }'
    

    如果可以,推荐使用httpie,类似 curl,但比 curl 更好用,将上面的命令换成 httpie,如下:

    http put :9200/movie/adventure/1 name="Life of Pi" actors:='["Suraj", "Irrfan"]'
    

    服务器返回的 JSON 对象,会给出Index、Type、Id、Version 等信息。
    成功返回的结果:

    {
        "_index": "movie",
        "_type": "adventure",
        "_id": "1",
        "_version": 1,
        "result": "created",
        "_shards": {
            "total": 2,
            "successful": 1,
            "failed": 0
        },
        "created": true
    }
    

    可以看到,我们已经成功创建了一个 _indexmovie_typeadventure_id 为 1 的文档,最后的1是该条记录的 Id。它不一定是数字,任意字符串(比如abc)都可以。

    ElasticSearch对于PUT请求的响应中包含了是否操作成功、文档编号等信息。

    GET
    我们通过 GET 请求来查看这个文档的信息:

    curl -XGET localhost:9200/movie/adventure/1
    

    结果如下:

    {
        "_index": "movie",
        "_type": "adventure",
        "_id": "1",
        "_version": 1,
        "found": true,
        "_source": {
            "name": "Life of Pi",
            "actors": [
                "Suraj",
                "Irrfan"
            ]
        }
    }
    

    可以看到,原始的文档数据存在了 _source 字段中。

    新增记录的时候,也可以不指定 Id,这时要改成 “POST” 请求。

    curl -X POST 'localhost:9200/movie/adventure' -d '
    {
      "name": "Life of Pi"
    }'
    

    更新整个文档
    更新记录就是使用 PUT 请求,重新发送一次数据。不过我们这次务必要加上需要修改的文档的ID编号,否则就变成添加了。接下来我们尝试对刚才新建立的文档进行些修改,添加某些关键字属性。

    当我们使用 PUT 方法指明文档的 _index, _type_id时,如果 _id 已存在,则新文档会替换旧文档,此时文档的 _version 会增加 1,并且 _created 字段为 false。比如:

    curl -XPUT "http://localhost:9200/movie/adventure/1" -d'
    {
        "name": "Life of Pi"
    }'
    

    返回的结果:

    {
        "_index": "movie",
        "_type": "adventure",
        "_id": "1",
        "_version": 2,
        "result": "updated",
        "_shards": {
            "total": 2,
            "successful": 1,
            "failed": 0
        },
        "created": false
    }
    

    添加和修改的比较
    对于此操作的ElasticSearch的响应与前者很类似,不过可以看出_version属性值已经发生了变化:

    变化的字段 添加 修改
    _version 1 2
    result created updated
    created true false

    GET
    最简单的获取某个文档的方式即是基于文档ID进行搜索

    curl -XGET 'http://localhost:9200/movie/adventure/1?pretty=true'
    

    返回的结果:

    {
      "_index" : "movie",
      "_type" : "adventure",
      "_id" : "1",
      "_version" : 2,
      "found" : true,
      "_source" : {
        "name" : "Life of Pi"
      }
    }
    

    可以看到,actors 这个字段已经不存在了,文档的 _version 变成了 2。

    如何避免原文档被替换?

    因此,为了避免在误操作的情况下,原文档被替换,我们可以使用_create 这个 API,表示只在文档不存在的情况下才创建新文档(返回 201 Created),如果文档存在则不做任何操作(返回 409 Conflict),命令如下:

    curl -XPUT "http://localhost:9200/movie/adventure/1/_create" -d'
    {                       
        "name": "Life of Pi"
    }'
    

    由于文档 id 存在,会返回 409 Conflict。结果如下:

    {
        "error": {
            "root_cause": [
                {
                    "type": "version_conflict_engine_exception",
                    "reason": "[adventure][1]: version conflict, document already exists (current version [2])",
                    "index_uuid": "Kn_OWg1TT5GLaMInWlREHQ",
                    "shard": "3",
                    "index": "movie"
                }
            ],
            "type": "version_conflict_engine_exception",
            "reason": "[adventure][1]: version conflict, document already exists (current version [2])",
            "index_uuid": "Kn_OWg1TT5GLaMInWlREHQ",
            "shard": "3",
            "index": "movie"
        },
        "status": 409
    }
    

    局部更新
    在有些情况下,我们只想更新文档的局部,而不是整个文档,这时我们可以使用 _update 这个 API。

    现在,待更新的文档信息如下:

    {
      "_index" : "movie",
      "_type" : "adventure",
      "_id" : "1",
      "_version" : 2,
      "found" : true,
      "_source" : {
        "name" : "Life of Pi"
      }
    }
    

    最简单的 update 请求接受一个局部文档参数 doc,它会合并到现有文档中,请求方式需要变更为POST方式:将对象合并在一起,存在的标量字段被覆盖,新字段被添加。

    curl -XPOST "http://localhost:9200/movie/adventure/1/_update" -d'
    {
        "doc": {
          "name": "life of pi",
          "actor": ["jack"]
       }
    }'
    

    上面的命令中,我们添加了一个新的字段:actors,结果如下:

    {
      "_index" : "movie",
      "_type" : "adventure",
      "_id" : "1",
      "_version" : 8,
      "found" : true,
      "_source" : {
        "name" : "life of pi",
        "actor" : [
          "jack"
        ]
      }
    }
    

    Delete:删除索引
    现在我们尝试去删除上文中插入的部分文档,对于要删除的文档同样需要传入索引名、类型名与文档名这些信息,譬如:

    curl -XDELETE "http://localhost:9200/movie/adventure/1"
    

    返回的结果:

    {
        "found": true,
        "_index": "movie",
        "_type": "adventure",
        "_id": "1",
        "_version": 3,
        "result": "deleted",
        "_shards": {
            "total": 2,
            "successful": 1,
            "failed": 0
        }
    }
    

    在我们删除了该文档之后,再次尝试用GET方法获取该文档信息时,会得到如下的响应:

    {
      "_index" : "movie",
      "_type" : "adventure",
      "_id" : "1",
      "found" : false
    }
    

    查看当前节点的所有 Index

    http://localhost:9200/_cat/indices?v
    

    返回的结果:

    health status index       uuid                   pri rep docs.count docs.deleted store.size pri.store.size
    yellow open   my_index    aBM6KLOLSJ6TWtp87sC5qA   5   1          1            0      4.1kb          4.1kb
    yellow open   accounts    2i3MNbwCSeSxZCBDikaMzA   5   1          2            0      7.9kb          7.9kb
    yellow open   movies      -uB5sD6QTt6vmD4YPpJFaQ   5   1          1            0      5.1kb          5.1kb
    yellow open   liuxingwang 6KRPO9fJRVmWC7X3G69HQQ   5   1          0            0       955b           955b
    

    小结

    • Elasticsearch 通过简单的 RESTful API 来隐藏 Lucene 的复杂性,从而让全文搜索变得简单
    • 在创建文档时,我们可以用 POST 方法指定将文档添加到某个 _index/_type下,来让 Elasticsearch自动生成唯一的 _id
    • 而用 PUT 方法指定将文档的 _index/_type/_id
    • 我们看不到HTTP头是因为我们没有让curl显示它们,如果要显示,使用curl命令后跟-i参数:

    相关文章

      网友评论

        本文标题:Elasticsearch CURD

        本文链接:https://www.haomeiwen.com/subject/eghovxtx.html