Elasticsearch学习笔记之文档的增删改查


title: "Elasticsearch学习笔记之文档的增删改查"
date: 2020-06-10T14:16:17+08:00
summary: "Elasticsearch学习笔记之文档的增删改查"


Elasticsearch相关概念讲解,参看官方博客 ,可以看下这篇文章对Elasticsearch来个初步印象:《终于有人把Elasticsearch原理讲透了》

笔记参考:

官方博客:开始使用Elasticsearch (1)

假设我们已经安装好Elasticsearch和Kibana,浏览器输入ip:5601,进入Kibana操作界面,这次我们使用到的是Kibana菜单里的Dev Tools功能,如图示:

dev-tools

创建文档

执行如下命令:

POST twitter/_doc/1
{
    "username":"Dannis",
    "uid":1
}

这行命令表明,向Elasticsearch发送一个POST请求,创建一个名为twitter的索引(index),同时生成一个文档,文档的ID为1,点击三角图标执行请求:

post-twitter-1

生成结果为:

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

我们来分析下返回的结果信息,_index表明我们创建的索引名为twitter_type类型是文档类型_doc_id文档ID为1,这些信息都是我们在请求里指定的,没问题,接下来,version表示版本号,result表明我们的操作属于创建created_shards表示分片信息,里面的信息表明有2个分片,成功1个,失败0个,这是什么意思呢?

我们执行GET _cat/shards/twitter命令,该命令是用来查看索引的分片信息,输出结果如下所示:

twitter 0 p STARTED    1 3.8kb 172.29.0.2 09baeea2d96a
twitter 0 r UNASSIGNED     

我们看到创建的索引twitter有两个分片,pprimary的首字母缩写,表示主分片,STAARTED表示分片正常。r又是什么呢?

我们再来看下索引的设置信息setting,输入并执行:

GET twitter/_settings

返回结果如下:

{
  "twitter" : {
    "settings" : {
      "index" : {
        "creation_date" : "1591930378288",
        "number_of_shards" : "1",
        "number_of_replicas" : "1",
        "uuid" : "3vc_AZQcQbGM-a6FtTSX5g",
        "version" : {
          "created" : "7070199"
        },
        "provided_name" : "twitter"
      }
    }
  }
}

可以看到索引的详细信息,creation_date表示索引的创建时间,以时间戳形式展示;number_of_shards表示主分片的数量,默认是1,number_of_replicas表示索引的副本数量,默认也是1。

回到上面GET _cat/shards/twitter命令的返回结果,我们知道了r 表示的是分片副本的意思,即replica的首字母,UNASSIGNED意为未分配,为什么是这个呢?这是因为我本地环境开启的的Elasticsearch环境为开发模式,只有一个节点,也就是主节点,如果开启的是集群模式,则副本数据则会自动分配到加入的节点上。

创建文档的时候,如果没有指定文档ID,Elasticsearch会自动给该文档生成一个ID,如下:

POST twitter/_doc
{
  "username":"test",
  "age":20
}

返回结果:

{
  "_index" : "twitter",
  "_type" : "_doc",
  "_id" : "EIcep3IBFDGGZnEIs9aT",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 4,
  "_primary_term" : 1
}

我们看到返回有将文档_id返回,再来查看一下:

GET twitter/_doc/EIcep3IBFDGGZnEIs9aT

返回内容正是我们期望写入的数据:

{
  "_index" : "twitter",
  "_type" : "_doc",
  "_id" : "EIcep3IBFDGGZnEIs9aT",
  "_version" : 1,
  "_seq_no" : 4,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "username" : "test",
    "age" : 20
  }
}

我们还可以通过调用_create方法来创建文档,如下:

POST twitter/_create/2
{
  "username":"GB",
  "uid":1,
  "city":"Guangzhou",
  "province":"Guangdong",
  "country":"China"
}

返回结果:

{
  "_index" : "twitter",
  "_type" : "_doc",
  "_id" : "2",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 6,
  "_primary_term" : 1
}

可知数据已成功写入,如果我们再次调用如下命令:

POST twitter/_create/2
{
  "username":"GB",
  "uid":1,
  "city":"Guangzhou",
  "province":"Guangdong",
  "country":"China"
}

返回结果如下:

{
  "error" : {
    "root_cause" : [
      {
        "type" : "version_conflict_engine_exception",
        "reason" : "[2]: version conflict, document already exists (current version [1])",
        "index_uuid" : "AiRNBupCRWWLFKqFSVW3mw",
        "shard" : "0",
        "index" : "twitter"
      }
    ],
    "type" : "version_conflict_engine_exception",
    "reason" : "[2]: version conflict, document already exists (current version [1])",
    "index_uuid" : "AiRNBupCRWWLFKqFSVW3mw",
    "shard" : "0",
    "index" : "twitter"
  },
  "status" : 409
}

返回错误,提示我们文档已经存在,那么如果执行下面的命令呢?

POST twitter/_doc/1
{
  "username":"Dannis",
  "uid":1
}

返回结果如下:

{
  "_index" : "twitter",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 7,
  "_primary_term" : 1
}

发现成功响应,只是result值变成了updated,并且版本号也变成了2,由此可知,如果使用POST twitter/_create/2方式来创建文档,只有该文档ID不存在才能创建成功,使用POST twitter/_doc/1方式来创建文档,如果文档不存在,则创建,如果文档已存在,则结果会变成对指定文档的更新操作,并且版本号加1。

查询文档

输入执行:

GET twitter/_doc/1

返回结果:

{
  "_index" : "twitter",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "username" : "Dannis",
    "uid" : 1
  }
}

可以看到我们定义的文档数据被放在了_source字段下面,found字段表示查到了该文档,如果我们输入以下命令:

GET twitter/_doc/2

返回结果:

{
  "_index" : "twitter",
  "_type" : "_doc",
  "_id" : "2",
  "found" : false
}

可以看到found为false。

修改文档

输入命令并执行:

POST twitter/_update/1
{
  "doc": {
    "username":"Dannis-update"
  }
}

返回结果:

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

我们看到result值变成了updated_version也变成了2,再查看一下:

GET twitter/_doc/1

返回结果:

{
  "_index" : "twitter",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 2,
  "_seq_no" : 1,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "username" : "Dannis-update",
    "uid" : 1
  }
}

没问题,username已变成了我们想要的。

如果我们更新的时候是加入一个不存在的字段,看下发生什么?输入以下命令并执行:

POST twitter/_update/1
{
  "doc": {
    "age":25
  }
}

返回结果:

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

可以看到文档的版本号变为3了。

再来查看一下,

GET twitter/_doc/1

返回结果:

{
  "_index" : "twitter",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 3,
  "_seq_no" : 2,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "username" : "Dannis-update",
    "uid" : 1,
    "age" : 25
  }
}

发现返回的_source里也包含了刚加的内容,由此可知,如果字段存在,则会更新原来的字段内容,如果字段不存在,则会添加新的字段内容。

删除文档

输入命令并执行:

DELETE twitter/_doc/1

返回结果:

{
  "_index" : "twitter",
  "_type" : "_doc",
  "_id" : "1",
  "_version" : 4,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 1,
    "failed" : 0
  },
  "_seq_no" : 3,
  "_primary_term" : 1
}

可看到_version变成了4,而result为deleted,由此发现,我们对文档每进行一次写入/更新操作,版本号都会加1。

我们再来查看一下:

GET twitter/_doc/1

返回结果:

{
  "_index" : "twitter",
  "_type" : "_doc",
  "_id" : "1",
  "found" : false
}

found为false,表示找不到ID为1的文档了,表明删除文档成功。

下面来看下对文档的批量操作。

批量创建文档

批量创建多个文档,输入以下命令并执行:

POST _bulk
{"index":{"_index":"twitter","_id":3}}
{"username":"张三","uid":3,"age":30}
{"index":{"_index":"twitter","_id":4}}
{"username":"李四","uid":4,"age":25}
{"index":{"_index":"twitter","_id":5}}
{"username":"王五","uid":5,"age":18}

返回结果:

{
  "took" : 44,
  "errors" : false,
  "items" : [
    {
      "index" : {
        "_index" : "twitter",
        "_type" : "_doc",
        "_id" : "3",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 9,
        "_primary_term" : 1,
        "status" : 201
      }
    },
    {
      "index" : {
        "_index" : "twitter",
        "_type" : "_doc",
        "_id" : "4",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 10,
        "_primary_term" : 1,
        "status" : 201
      }
    },
    {
      "index" : {
        "_index" : "twitter",
        "_type" : "_doc",
        "_id" : "5",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 11,
        "_primary_term" : 1,
        "status" : 201
      }
    }
  ]
}

没有异常,如果我们想同时往不同的索引里写入数据呢?执行以下命令:

POST _bulk
{"index":{"_index":"twitter","_id":6}}
{"username":"Jack","uid":6,"age":22}
{"index":{"_index":"twitter_v1","_id":1}}
{"username":"test","age":20}

我们同时往twittertwitter_v1各写入一条数据,分别用GET twitter/_doc/6GET twitter_v1/_doc/1查询,都能正常查询到。

批量查询文档

如果我们想同时查询多个文档,可执行如下命令:

GET _mget
{
  "docs":[
    {
      "_index":"twitter",
      "_id":1
    },
    {
      "_index":"twitter",
      "_id":2
    }
  ]
}

返回结果:

{
  "docs" : [
    {
      "_index" : "twitter",
      "_type" : "_doc",
      "_id" : "1",
      "_version" : 3,
      "_seq_no" : 8,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "username" : "GB",
        "uid" : 1,
        "city" : "Guangzhou2",
        "province" : "Guangdong",
        "country" : "China"
      }
    },
    {
      "_index" : "twitter",
      "_type" : "_doc",
      "_id" : "2",
      "_version" : 1,
      "_seq_no" : 6,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "username" : "GB",
        "uid" : 1,
        "city" : "Guangzhou",
        "province" : "Guangdong",
        "country" : "China"
      }
    }
  ]
}

这是同时查同一个索引的文档,也可以同时查多个索引下的文档,比如:

GET _mget
{
  "docs":[
    {
      "_index":"twitter",
      "_id":1
    },
    {
      "_index":"twitter_v1",
      "_id":1
    }
  ]
}

结果如下:

{
  "docs" : [
    {
      "_index" : "twitter",
      "_type" : "_doc",
      "_id" : "1",
      "_version" : 3,
      "_seq_no" : 8,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "username" : "GB",
        "uid" : 1,
        "city" : "Guangzhou2",
        "province" : "Guangdong",
        "country" : "China"
      }
    },
    {
      "_index" : "twitter_v1",
      "_type" : "_doc",
      "_id" : "1",
      "_version" : 1,
      "_seq_no" : 0,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "username" : "test",
        "age" : 20
      }
    }
  ]
}

批量更新文档

批量更新文档,执行如下命令:

POST _bulk
{"update":{"_index":"twitter","_id":1}}
{"doc":{"username":"GB-update"}}
{"update":{"_index":"twitter_v1","_id":1}}
{"doc":{"age":25}}

返回结果:

{
  "took" : 107,
  "errors" : false,
  "items" : [
    {
      "update" : {
        "_index" : "twitter",
        "_type" : "_doc",
        "_id" : "1",
        "_version" : 4,
        "result" : "updated",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 13,
        "_primary_term" : 1,
        "status" : 200
      }
    },
    {
      "update" : {
        "_index" : "twitter_v1",
        "_type" : "_doc",
        "_id" : "1",
        "_version" : 2,
        "result" : "updated",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 1,
        "_primary_term" : 1,
        "status" : 200
      }
    }
  ]
}

我们再用以下命令查询一下:

GET _mget
{
  "docs":[
    {
      "_index":"twitter",
      "_id":1
    },
    {
      "_index":"twitter_v1",
      "_id":1
    }
  ]
}

返回结果如下所示,发现数据都变成了我们想要的内容。

{
  "docs" : [
    {
      "_index" : "twitter",
      "_type" : "_doc",
      "_id" : "1",
      "_version" : 4,
      "_seq_no" : 13,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "username" : "GB-update",
        "uid" : 1,
        "city" : "Guangzhou2",
        "province" : "Guangdong",
        "country" : "China"
      }
    },
    {
      "_index" : "twitter_v1",
      "_type" : "_doc",
      "_id" : "1",
      "_version" : 2,
      "_seq_no" : 1,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "username" : "test",
        "age" : 25
      }
    }
  ]
}

批量删除文档

批量删除文档跟批量更新的命令类似,如下:

POST _bulk
{"delete":{"_index":"twitter","_id":1}}
{"delete":{"_index":"twitter_v1","_id":1}}

返回结果:

{
  "took" : 80,
  "errors" : false,
  "items" : [
    {
      "delete" : {
        "_index" : "twitter",
        "_type" : "_doc",
        "_id" : "1",
        "_version" : 5,
        "result" : "deleted",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 14,
        "_primary_term" : 1,
        "status" : 200
      }
    },
    {
      "delete" : {
        "_index" : "twitter_v1",
        "_type" : "_doc",
        "_id" : "1",
        "_version" : 3,
        "result" : "deleted",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 2,
        "_primary_term" : 1,
        "status" : 200
      }
    }
  ]
}

我们再用GET _mget命令去查这两个文档的时候,发现是找不到数据了,返回结果如下:

{
  "docs" : [
    {
      "_index" : "twitter",
      "_type" : "_doc",
      "_id" : "1",
      "found" : false
    },
    {
      "_index" : "twitter_v1",
      "_type" : "_doc",
      "_id" : "1",
      "found" : false
    }
  ]
}

同时进行创建、更新、删除文档操作

通过上面的例子我们发现,对文档的批量操作都是通过_bulk命令来操作,只是传入的参数不同,那么可不可以同时进行创建、更新、删除操作呢?试一下:

POST _bulk
{"index":{"_index":"twitter","_id":10}}
{"username":"小飞飞","age":12}
{"update":{"_index":"twitter","_id":3}}
{"doc":{"username":"张三-update"}}
{"delete":{"_index":"twitter","_id":6}}

返回结果:

{
  "took" : 51,
  "errors" : false,
  "items" : [
    {
      "index" : {
        "_index" : "twitter",
        "_type" : "_doc",
        "_id" : "10",
        "_version" : 1,
        "result" : "created",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 15,
        "_primary_term" : 1,
        "status" : 201
      }
    },
    {
      "update" : {
        "_index" : "twitter",
        "_type" : "_doc",
        "_id" : "3",
        "_version" : 2,
        "result" : "updated",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 16,
        "_primary_term" : 1,
        "status" : 200
      }
    },
    {
      "delete" : {
        "_index" : "twitter",
        "_type" : "_doc",
        "_id" : "6",
        "_version" : 2,
        "result" : "deleted",
        "_shards" : {
          "total" : 2,
          "successful" : 1,
          "failed" : 0
        },
        "_seq_no" : 17,
        "_primary_term" : 1,
        "status" : 200
      }
    }
  ]
}

我们再来批量查询一下:

GET _mget
{
  "docs":[
    {
      "_index":"twitter",
      "_id":10
    },
    {
      "_index":"twitter",
      "_id":3
    },
    {
      "_index":"twitter",
      "_id":6
    }
  ]
}

返回结果:

{
  "docs" : [
    {
      "_index" : "twitter",
      "_type" : "_doc",
      "_id" : "10",
      "_version" : 1,
      "_seq_no" : 15,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "username" : "小飞飞",
        "age" : 12
      }
    },
    {
      "_index" : "twitter",
      "_type" : "_doc",
      "_id" : "3",
      "_version" : 2,
      "_seq_no" : 16,
      "_primary_term" : 1,
      "found" : true,
      "_source" : {
        "username" : "张三-update",
        "uid" : 3,
        "age" : 30
      }
    },
    {
      "_index" : "twitter",
      "_type" : "_doc",
      "_id" : "6",
      "found" : false
    }
  ]
}

发现数据都符合预期。

到这里,发现了通过bulk创建文档时,参数:{"index":{"_index":"twitter","_id":10}}里的index其实是个动词,即创建索引,特此说明。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,039评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,223评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,916评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,009评论 1 291
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,030评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,011评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,934评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,754评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,202评论 1 309
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,433评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,590评论 1 346
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,321评论 5 342
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,917评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,568评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,738评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,583评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,482评论 2 352