Elasticsearch初步使用案例
Elasticsearch的使用
接下来,我们看看如何建立索引、创建文档等,就好比在 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 来执行上述操作,如图所示:
- 用
url
表示一个资源,比如/movie/adventure/1
就表示一个index
为movie
,type
为adventure
,id
为1
的document
- 用
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 }
可以看到,我们已经成功创建了一个 _index
为 movie
,_type
为 adventure
,_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
参数。
相关推荐
另外一部分,则需要先做聚类、分类处理,将聚合出的分类结果存入ES集群的聚类索引中。数据处理层的聚合结果存入ES中的指定索引,同时将每个聚合主题相关的数据存入每个document下面的某个field下。