文档
什么是文档
程序中大多的实体或对象能够被序列化为包含键值对的JSON对象,键(key)是字段(field)或属性(property)的名字,值(value)可以是字符串、数字、布尔类型、另一个对象、值数组或者其他特殊类型,比如表示日期的字符串或者表示地理位置的对象
1 | { |
通常,我们可以认为对象(object)和文档(document)是等价相通的。不过,他们还是有所差别:对象(Object)是一个JSON结构体——类似于哈希、hashmap、字典或者关联数组;对象(Object)中还可能包含其他对象(Object)。 在Elasticsearch中,文档(document)这个术语有着特殊含义。它特指最顶层结构或者根对象(root object)序列化成的JSON数据(以唯一ID标识并存储于Elasticsearch中)。
归结
Json Object,由字段组成:
- 字符串:text, keyword
- 数值型:long,integer,short,byte,double,float,half_float,scled_float
- 布尔:boolean
- 日期:date
- 二进制:binary
- 范围类型:integer_range,float_range,long_range,double_range,date_range
每个文档有唯一的id标识
- 自行指定
- es生成
元数据,用于标注文档的相关信息
- _index:文档所在的索引名
- _type:文档所在的类型名
- _id:文档唯一id
- _uid:组合id,由_type和_id组成(6.x_type不再起作用,同_id一样)
- _source:文档的原始Json数据,可以从这里获取每个字段的内容
- _all:整合所有字段内容到该字段,默认禁用
文档元数据
一个文档不只有数据。它还包含了元数据(metadata)——关于文档的信息。三个必须的元数据节点是:
节点 | 说明 |
---|---|
_index | 文档存储的地方 |
_type | 文档代表的对象的类 |
_id | 文档的唯一标识 |
_index
索引(index)类似于关系型数据库里的“数据库”——它是我们存储和索引关联数据的地方。
事实上,我们的数据被存储和索引在分片(shards)中,索引只是一个把一个或多个分片分组在一起的逻辑空间。然而,这只是一些内部细节——我们的程序完全不用关心分片。对于我们的程序而言,文档存储在索引(index)中。剩下的细节由Elasticsearch关心既可。
_type
在应用中,我们使用对象表示一些“事物”,例如一个用户、一篇博客、一个评论,或者一封邮件。每个对象都属于一个类(class),这个类定义了属性或与对象关联的数据。user类的对象可能包含姓名、性别、年龄和Email地址。
在关系型数据库中,我们经常将相同类的对象存储在一个表里,因为它们有着相同的结构。同理,在Elasticsearch中,我们使用相同类型(type)的文档表示相同的“事物”,因为他们的数据结构也是相同的。
每个类型(type)都有自己的映射(mapping)或者结构定义,就像传统数据库表中的列一样。所有类型下的文档被存储在同一个索引下,但是类型的映射(mapping)会告诉Elasticsearch不同的文档如何被索引。
在7.0前,一个index可以设置多个type,在7.0后type统一为_doc
_id
id仅仅是一个字符串,它与_index和_type组合时,就可以在Elasticsearch中唯一标识一个文档。当创建一个文档,你可以自定义_id,也可以让Elasticsearch帮你自动生成。
Index Api
以下操作均在es7.2版本操作
Index(createorupdate)
PUT {_index}/{_type}/{_id}
POST {_index}/{_type}/{_id}(id可不指定)
创建一个索引
1 | PUT test_index |
创建一个索引并指定文档内容和id
1 | PUT /test_index/_doc/1 |
创建一个索引指定文档内容自动生成id
1 | POST /test_index/_doc |
文档不存在执行的是创建操作,存在的话回变为更新操作,并且_version会增加1
Create
有两种方式:
第一种方法使用op_type查询参数:
1 | PUT /test_index/_doc/1?op_type=create |
或者第二种方法是在URL后加/_create做为端点:
1 | PUT /test_index/_doc/1/_create |
如果请求成功的创建了一个新文档,Elasticsearch将返回正常的元数据且响应状态码是201 Created。
另一方面,如果包含相同的_index、_type和_id的文档已经存在,Elasticsearch将返回409 Conflict响应状态码,错误信息类似如下:
1 | { |
POST和PUT的区别是POST不用加具体的id,它是作用在一个集合资源之上的(/uri),而PUT操作是作用在一个具体资源之上的(/uri/xxx)。
在ES中,如果不确定document的ID(documents具体含义见下),那么直接POST对应uri( “POST /website/blog” ),ES可以自己生成不会发生碰撞的UUID;
如果确定document的ID,比如 “PUT /website/blog/123”,那么执行创建或修改(修改时_version版本号提高1)
Update
1 | PUT /test_index/_update/1 |
Delete
1 | DELETE test_index |
Get
获取所有
1 | GET /test_index/_search |
指定id
1 | GET /test_index/_doc/1 |
归结
操作 | 请求 |
---|---|
Create | PUT /test_index/_doc/1/_create {“username”:”alfred”,”age”:1} POST /test_index/_doc/ {“username”:”alfred”,”age”:1}(不指定id自动生成) |
Index | PUT Or POST /test_index/_doc/1/ {“username”:”alfred”,”age”:1} |
Read | GET /test_index/_doc/1 |
Update | POST /test_index/_update/1 {“doc”: {“sex”: “女”}} |
Delete | DELETE test_index2 |
Index和Update
Index实际上是文档不存在会创建一个文档,存在则会删除原来的文档,新的文档被索引,并且version加1
Update不会删除原来的文档,实现真正的更新,POST方法的payload需包含在”doc”里
Bulk
1 | POST _bulk |
批量查询api
es允许一次查询多个文档,如果你需要从Elasticsearch中检索多个文档,相对于一个一个的检索,更快的方式是在一个请求中使用multi-get或者mget API。
mget API参数是一个docs数组,数组的每个节点定义一个文档的_index、_type、_id元数据。如果你只想检索一个或几个确定的字段,也可以定义一个_source参数:
1 | POST _mget |
响应体也包含一个docs数组,每个文档还包含一个响应,它们按照请求定义的顺序排列。每个这样的响应与单独使用get request响应体相同:
1 | { |
如果你想检索的文档在同一个_index中,你就可以在URL中定义一个默认的/_index。
你依旧可以在单独的请求中使用这些值:
1 | POST /test_index/_doc/_mget |
在7.0以上版本后,_doc在mget中可以省略,不省略会提示#! Deprecation: [types removal] Specifying types in multi get requests is deprecated.
事实上,如果所有文档具有相同_index,你可以通过简单的ids数组来代替完整的docs数组:
1 | POST /test_index/_mget |
不存在的文档会显示found:false
1 | { |
尽管前面提到有一个文档没有被找到,但HTTP请求状态码还是200。事实上,就算所有文档都找不到,请求也还是返回200,原因是mget请求本身成功了。如果想知道每个文档是否都成功了,你需要检查found标志。