什么是文档?
通常,我们可以认为对象(object)和文档(document)是等价相通的。不过,他们还是有所差
别:对象(Object)是一个JSON结构体——类似于哈希、hashmap、字典或者关联数组;对象
(Object)中还可能包含其他对象(Object)。 在Elasticsearch中,文档(document)这个术语有着特殊含义。它特指最顶层结构或者根对象(root object)序列化成的JSON数据(以唯一ID标识
并存储于Elasticsearch中)
文档元数据
一个文档不只有数据。它还包含了元数据(metadata)——关于文档的信息。
_index:文档存储的地方
_type:文档代表的对象的类
_id:文档的唯一id
索引创建原则
- 类似的数据放在一个索引,非类似的数据放不同索引:product index(包含了所有的商品),sales index(包含了所有的商品销售数据),inventory index(包含了所有库存相关的数据)。如果你把比如product,sales,human resource(employee),全都放在一个大的index里面,比如说company index,不合适的。
- index中包含了很多类似的document:类似是什么意思,其实指的就是说,这些document的fields很大一部分是相同的,你说你放了3个document,每个document的fields都完全不一样,这就不是类似了,就不太适合放到一个index里面去了。
- 索引名称必须是小写的,不能用下划线开头,不能包含逗号:product,website,blog
创建索引、类型、文档(接口的方式)
以kibana的方式操作ES的可以查看ElasticSearch教程——Kibana简单操作ES
以博客内容管理为例,索引名为blog,类型为article,自定义id是“1”,新加一个文档:
- curl -H 'Content-Type:application/json' -XPUT http://localhost:9200/blog/article/1 -d '
- {
- "id": "1",
- "title": "New version of Elasticsearch released!",
- "content": "Version 1.0 released today!",
- "priority": 10,
- "tags": ["announce", "elasticsearch", "release"]
- }'
自增ID
当我们想要一个自增ID的时候,直接不用设置id即可,即原来是把文档存储到某个ID对应的空间,现在是把这个文档添加到某个_type下(注意:这边是POST不是PUT)
- curl -H 'Content-Type:application/json' -XPOST http://localhost:9200/blog/article/ -d '
- {
- "title": "New version of Elasticsearch released!",
- "content": "Version 1.0 released today!",
- "priority": 10,
- "tags": ["announce", "elasticsearch", "release"]
- }'
返回结果:
- {
- "_index": "blog",
- "_type": "article",
- "_id": "eTmX5mUBtZGWutGW0TNs",
- "_version": 1,
- "result": "created",
- "_shards": {
- "total": 2,
- "successful": 1,
- "failed": 0
- },
- "_seq_no": 0,
- "_primary_term": 1
- }
自动生成的id,长度为20个字符,URL安全,base64编码,GUID,分布式系统并行生成时不可能会发生冲突。
检索文档
在对应的浏览器地址栏输入如下地址
http://XXX.XXX.XXX.XX:9200/blog/article/1?pretty
或者在Linux中使用如下脚本:
curl -H 'Content-Type:application/json' -XGET http://localhost:9200/blog/article/1?pretty
响应包含了现在熟悉的元数据节点,增加了_source字段,它包含了在创建索引时我们发送给Elasticsearch的原始文档。
pretty:在任意的查询字符串中增加pretty参数,类似于上面的例子。会让Elasticsearch美化输出(pretty-print)JSON响应以便更加容易阅读。
_source字段不会被美化,它的样子与我们输入的一致,现在只包含我们请求的字段,而且过滤了date字段。
或者你只想得到_source字段而不要其他的元数据,你可以这样请求:
curl -H 'Content-Type:application/json' -XGET http://localhost:9200/blog/article/1/_source
返回结果:
- {
- "id": "1",
- "title": "New version of Elasticsearch released!",
- "content": "Version 1.0 released today!",
- "priority": 10,
- "tags": ["announce", "elasticsearch", "release"]
- }
请求返回的响应内容包括{"found": true}。这意味着文档已经找到。如果我们请求一个不存在的文档,依旧会得到一个JSON,不过found值变成了false。此外,HTTP响应状态码也会变成'404 Not Found'代替'200 OK'。我们可以在curl后加-i参数得到响应头:
curl -H 'Content-Type:application/json' -i -XGET http://localhost:9200/blog/article/1?pretty
显示结果:
- HTTP/1.1 200 OK
- content-type: application/json; charset=UTF-8
- content-length: 337
- {
- "_index" : "blog",
- "_type" : "article",
- "_id" : "1",
- "_version" : 1,
- "found" : true,
- "_source" : {
- "id" : "1",
- "title" : "New version of Elasticsearch released!",
- "content" : "Version 1.0 released today!",
- "priority" : 10,
- "tags" : [
- "announce",
- "elasticsearch",
- "release"
- ]
- }
- }
更新文档
- curl -H 'Content-Type:application/json' -XPOST http://localhost:9200/blog/article/1/_update -d '{
- "script": "ctx._source.content = \"new content\""
- }'
删除文档
curl -XDELETE http://localhost:9200/blog/article/1
冲突,并发与锁
数据库离不开锁的问题。MYSQL在这方面可是相当的复杂,涉及到两种引擎,四种隔离级别,undo和redo,当前读和快照读等一系列麻烦的东西。不过es显性有version字段,看起来似乎没那么复杂。使用的乐观锁。贴一段介绍吧
悲观并发控制(Pessimistic concurrency control) 这在关系型数据库中被广泛的使用,假设冲突的更改经常发生,为了解决冲突我们把访问区 块化。典型的例子是在读一行数据前锁定这行,然后确保只有加锁的那个线程可以修改这行 数据。 乐观并发控制(Optimistic concurrency control): 被Elasticsearch使用,假设冲突不经常发生,也不区块化访问,然而,如果在读写过程中数 据发生了变化,更新操作将失败。这时候由程序决定在失败后如何解决冲突。实际情况中, 可以重新尝试更新,刷新数据(重新读取)或者直接反馈给用户。