一: 新增文档POST /{index}/{type} 或 PUT /{index}/{type}/{id}

注意:新增文档时可以显式指定id,id可以是数字也可以是字符串,如果不显示指定id,系统会自动生成一个唯一的id值

PUT /shop/goods/1
{
    "name": "Apple/苹果 iPhone X",
    "price": 9688.00,
    "quantity": 999,
    "colors": ["银色", "深空灰色"],
    "is_discount": true,
    "create_date": "2018-01-31 12:10:30",
    "ip_addr": "192.168.10.1",
    "location": "39.92733,116.39507",
    "merchant": {
        "id": 2222,
        "shop_name": "水果店"
    },
    "params": [
       {"id": 1, "label":"型号", "value": "iphone x"},
       {"id": 2, "label":"品牌", "value": "Apple/苹果"}
    ]
}

指定id和不指定id的区别:

  • 如果使用post不指定id,这时的操作肯定是添加操作,因为id是系统生成的,唯一的(类似于关系型数据库,id是自增主键,属于一种insert操作);
  • 如果使用put指定id,当id在类型中还没有存在时,此时和post的操作效果完全一样(也是属于一种insert操作,只不过id使用指定的id,不由数据库自动生成了);
  • 如果使用put指定id,当id已经在类型中存在了,此时就不是一种添加操作了,而是一种更新操作,也就是说put方式既可以新增文档,又可以更新文档(类似于关系型数据库中的save or update 操作,主键不存在时进行insert,主键存在时update操作)

如何使用put方式只进行新增操作,如果id存在了,直接返回一个错误状态409表示冲突,而不是把文档更新掉?有两种方式一种在路径上使用_create,另一种使用参数的方式,使用op_type=create,两种方式完全一样,只是使用风格不一样
PUT /{index}/{type}/{id}/_create 或 PUT /{index}/{type}/{id}?op_type=create

PUT /shop/goods/1/_create
{
    "name": "Apple/苹果 iPhone X",
    "price": 9688.00,
    "quantity": 999,
    "colors": ["银色", "深空灰色"],
    "is_discount": true,
    "create_date": "2018-01-31 12:10:30",
    "ip_addr": "192.168.10.1",
    "location": "39.92733,116.39507",
    "merchant": {
        "id": 2222,
        "shop_name": "水果店"
    },
    "params": [
       {"id": 1, "label":"型号", "value": "iphone x"},
       {"id": 2, "label":"品牌", "value": "Apple/苹果"}
    ]
}

// 返回结果
{
  "error": {
    "root_cause": [
      {
        "type": "version_conflict_engine_exception",
        "reason": "[goods][1]: version conflict, document already exists (current version [1])",
        "index_uuid": "MFndQ_JVQyiPXg1WBDvgpg",
        "shard": "3",
        "index": "shop"
      }
    ],
    "type": "version_conflict_engine_exception",
    "reason": "[goods][1]: version conflict, document already exists (current version [1])",
    "index_uuid": "MFndQ_JVQyiPXg1WBDvgpg",
    "shard": "3",
    "index": "shop"
  },
  "status": 409
}

二:更新文档

注意:在Elasticsearch中文档是不能直接被修改的,当修改文档时es会将旧文档标记为删除状态然后再讲修改的文档作为一条新的文档添加进来, 这样就是间接的达到更新文档的目的。被标记为删除状态的文档并不会立即消失,你也无法访问他,es会在你继续添加更多数据的时候在后台清理已经删除的文件。所以此种方式更新需要列举出来所有字段,如果只更新一个字段的值,那么该文档的所有字段以及对应的值都要列举出来,因为内部更新方式是先删除文档再添加文档,因为是这种原理,所以也可以用于达到删除字段的目的:更新时列举除了要删除的字段的所有文档,然后进行更新。

变相的局部更新:一般是先查出该文档,然后修改个别字段的值,然后再更新该文档,这样可以达到只更新某个字段。

PUT /shop/goods/1
{
    "name": "Apple/苹果 iPhone X",
    "price": 8888.00,
    "quantity": 999,
    "colors": ["银色", "深空灰色", "脑残粉"],
    "is_discount": true,
    "create_date": "2018-01-31 12:10:30",
    "ip_addr": "192.168.10.1",
    "location": "39.92733,116.39507",
    "merchant": {
        "id": 2222,
        "shop_name": "水果店"
    },
    "params": [
       {"id": 1, "label":"型号", "value": "iphone x"},
       {"id": 2, "label":"品牌", "value": "Apple/苹果"}
    ]
}

// 返回结果中有一个字段版本_version:刚插入文档时值为1,每次更新,删除操作时这个版本号都会加1;result字段:在添加文档时值为"created",当更新文档时值为updated
{
  "_index": "shop",
  "_type": "goods",
  "_id": "1",
  "_version": 2,
  "result": "updated",
  "_shards": {
    "total": 2,
    "successful": 1,
    "failed": 0
  },
  "_seq_no": 2,
  "_primary_term": 1
}

局部更新 POST /{index}/{type}/{id}/_update

当字段存在时替换字段的值,当字段不存在时将字段添加到文档中。此种方式只需列举要修改的字段,不修改的字段就不需要列举出来,将要修改的字段放在doc中

// 修改价格,大降价;修改颜色:隔壁老王绿;增加cpu字段
POST /shop/goods/3/_update
{
    "doc": {
      "price": 666.00,
      "colors": ["老王绿"],
      "cpu": "A11111111" 
    }
}

脚本更新

脚本更新更加灵活,脚本语言可以在更新API中被用来修改_source中的内容,而它在脚本中被称为ctx._source

使用脚本来增加库存数量:
POST /shop/goods/3/_update
{
   "script" : "ctx._source.quantity+=1"
}
使用脚本在颜色数组中添加新的颜色。在这个例子中,我们把新的颜色声明为一个变量,而不是将他写死在脚本中。这样Elasticsearch就可以重新使用这个脚本进行添加新的颜色,而不用再次重新编写脚本了:
POST /shop/goods/3/_update
{
  "script": {
    "inline": "ctx._source.colors.add(params.new_color)", 
    "params": {
      "new_color": "脑残粉"
    }
  }
}
使用ctx.op来根据内容选择是否删除一个文档:
POST /shop/goods/3/_update
{
  "script": {
    "inline": "ctx.op = ctx._source.cpu == params.cpu ? 'delete' : 'none'", 
    "params": {"cpu": "A11111111"}
    }
}
当更新一个文档不存在时会报错,如果更新时当文档不存在时就创建可以使用upsert
upsert参数,指定如果文档不存在就应该先创建它:
POST /website/pageviews/1/_update
{
   "script" : "ctx._source.views+=1",
   "upsert": {
       "views": 1
   }
}
// 我们第一次运行这个请求时, upsert 值作为新文档被索引,初始化 views 字段为 1 。 在后续的运行中,由于文档已经存在,script 更新操作将替代 upsert 进行应用,对 views 计数器进行累加。

查询文档 GET /{index}/{type}/{id}

GET /{index}/{type}/{id}/_source 只获取文档的源数据,不获取文档的元数据
查询文档方式很多,后面博客将单独探讨

判断文档是否存在 HEAD /{index}/{type}/{id}

存在返回200 - OK,不存在返回404 - Not Found

删除文档 DELETE /{index}/{type}/{id}

注意:删除一个文档也不会立即生效,它只是被标记成已删除状态。es将会在你之后添加更多索引的时候才会在后台进行删除内容的清理,删除时即使文档不存在版本号也会加1

查看文档总数量 GET /{index}/{type}/_count


我的微信公众号:

Elasticsearch入门教程(四):Elasticsearch文档CURD_Apple