Elastic Search 入门
安装Elastic Search#
安装成功之后验证
<code>curl -X GET http://localhost:9200/?pretty
{
"name" : "ZKKlE0t",
"cluster_name" : "es",
"cluster_uuid" : "sI09KISmQNaGMgbuN7S4gQ",
"version" : {
"number" : "6.6.1",
"build_flavor" : "default",
"build_type" : "tar",
"build_hash" : "1fd8f69",
"build_date" : "2019-02-13T17:10:04.160291Z",
"build_snapshot" : false,
"lucene_version" : "7.6.0",
"minimum_wire_compatibility_version" : "5.6.0",
"minimum_index_compatibility_version" : "5.0.0"
},
"tagline" : "You Know, for Search"
}/<code>
分片#
分片是Elasticsearch在集群中分发数据的关键,分片是数据的容器,文档都存储在问片中,然后分片被分配到集群中的节点上, 当你的集群扩容或缩小,ES会自动在节点之间迁移分片, 使集群保持平衡
分片可以是主分片(primary shard)或者是复制分片。索引中每个文档属于一个单独的主分片,复制分片是主分片的一个单独的副本, 作为冗余数据,防止硬件故障导致数据丢失。
当索引创建完成时, 主分片的数量就固定了,但是复制分片的数量可以随时调整。
创建索引:
<code>curl -X PUT http://localhost:9200/blogs -H "Content-Type: application/json" -d '{ "settings": { "number_of_shards": 3, "number_of_replicas": 1 } }'
> Response
{"acknowledged":true,"shards_acknowledged":false,"index":"blogs"}/<code>
启动多个node实例#
<code>elasticsearch -Epath.data=$ELASTIC_HOME/data/es1 -Epath.logs=$ELASTIC_HOME/logs/es1
elasticsearch -Epath.data=$ELASTIC_HOME/data/es2 -Epath.logs=$ELASTIC_HOME/logs/es2
elasticsearch -Epath.data=$ELASTIC_HOME/data/es3 -Epath.logs=$ELASTIC_HOME/logs/es3/<code>
<code>curl -X GET http://localhost:9200/_cluster/health/?pretty
{
"cluster_name" : "es",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 2,
"number_of_data_nodes" : 2,
"active_primary_shards" : 0,
"active_shards" : 0,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 0,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 100.0
}/<code>
其中status为green
颜色意义green所有分片和复制分片都可用yellow所有主要分片可用,但复制分片不是都可用red不是所有主要分片可用
数据结构#
一个文档除了信息数据之外还必须包括元数据,Elasticsearch中必须有如下元数据节点:
节点意义_index文档存储的地方_type文档代表对象的类_id文档的唯一标识
- _index 索引类似与关系数据库里的数据库, 它是存储和索引关联数据的地方
- _type 在关系型数据库中,我们将相同类的对象存储在一个表里,因为他们有相同的结构,在Elasticsearch中,我们使用相同类型(type)的文档表示相同的事物,他们的数据结构是相同的
- _id 是一个字符串,与_index和_type组合时,就可以在Elasticsearch中唯一标识一个文档,当创建文档时,你可以自定义_id,也可由系统帮你生成
和关系型数据库做一个类比 Relational DB ⇒ Databases ⇒ Tables ⇒ Rows ⇒ Columns Elasticsearch ⇒ Indices ⇒ Types ⇒ Documents ⇒ Fields
基本操作#
假设我们的索引为blog,类型为post,
- 创建索引
使用PUT方法时, 我们可以指定ID,如果希望系统自动生成, 可以使用POST
<code>**手动赋值ID**
curl -X PUT -H "Content-Type: application/json" \\
-d '{ "title": "First blog", "text": "Elastic search", "date": "2018/01/01" }' http://localhost:9200/blog/post
{
"_index" : "blog",
"_type" : "post",
"_id" : "123",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"title" : "First blog",
"text" : "Elastic search",
"date" : "2018/01/01"
}
}
**自动生成**
curl -X POST -H "Content-Type: application/json" \\
-d '{ "title": "First blog", "text": "Elastic search", "date": "2018/01/01" }' http://localhost:9200/blog/post
{
"_index" : "blog",
"_type" : "post",
"_id" : "dKg7KWkBMu7m9eCgyDUF",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"title" : "First blog",
"text" : "Elastic search",
"date" : "2018/01/01"
}
}/<code>
- 检索文档
请求时追加pretty返回结果会对json进行格式化,如果响应内容中found为true表示文档存在,如果文档不存在同样会返回结果,found为false
<code>curl -X GET http://localhost:9200/blog/post/123?pretty
{
"_index" : "blog",
"_type" : "post",
"_id" : "123",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"title" : "First blog",
"text" : "Elastic search",
"date" : "2018/01/01"
}
}
curl -X GET http://localhost:9200/blog/post/1234?pretty
{
"_index" : "blog",
"_type" : "post",
"_id" : "1234",
"found" : false
}/<code>
- 检索文档中的部分字段
GET 请求会返回文档的全部内容, 存储在_source,如果你只想显示部分字段,可以使用_source字段过滤
<code>curl -X GET http://localhost:9200/blog/post/123?pretty&_source=title,text
{
"_index" : "blog",
"_type" : "post",
"_id" : "123",
"_version" : 1,
"_seq_no" : 0,
"_primary_term" : 1,
"found" : true,
"_source" : {
"text" : "Elastic search",
"title" : "First blog"
}
}/<code>
- 检查文档是否存在
存在返回200,不存在返回404
<code>curl -I http://localhost:9200/blog/post/123
HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 184/<code>
<code>curl -I http://localhost:9200/blog/post/1234
HTTP/1.1 404 Not Found
content-type: application/json; charset=UTF-8
content-length: 59/<code>
- 更新文档
更新文档时,原有文档会被标记为删除,不可访问,新文档版本号会+1
<code>curl -X PUT -H "Content-Type: application/json" http://localhost:9200/blog/post/123 -d '{ "title": "Update blog" }'
{
"_index" : "blog",
"_type" : "post",
"_id" : "123",
"_version" : 2,
"_seq_no" : 1,
"_primary_term" : 1,
"found" : true,
"_source" : {
"title" : "Update blog"
}
}/<code>
局部更新
使用update API更新文档时,会接受一个局部文档参数doc,它会合并到现有文档中,对象合并在一起,已经存在的字段被覆盖, 新字段 则追加到原文档
<code>curl -X POST -H "Content-Type: application/json" http://localhost:9200/blog/post/123/_update -d '{ "doc": { "title": "Update partial blog", "views": 0 }}'
{
"_index" : "blog",
"_type" : "post",
"_id" : "123",
"_version" : 3,
"_seq_no" : 2,
"_primary_term" : 1,
"found" : true,
"_source" : {
"title" : "Update partial blog",
"views" : 0
}
}/<code>
文档冲突#
由于Elasticsearch是分布式结构的,每个文档可能存储在不同的分片上,当多个进程同时更新文档时可能会出现写冲突, 这时可能会出现脏数据。 类比关系型数据库中的写冲突解决方法
- 悲观锁:假设任何情况下都会发生冲突,写数据时先请求锁,得到锁之后写数据,完成后释放锁
- 乐观锁:假设不会造成冲突,直接去写, 写数据的时候进行版本比较,如果不一致,说明有其他进程修改过,抛出异常 我们可以通过版本号来解决Elasticsearch中的写冲突问题 在提交更新的时候加入版本号,如果版本号一致则修改,不一致则跳过
<code>curl -X POST -H "Content-Type: application/json" http://localhost:9200/blog/post/123?version=1 -d '{ "title": "Update partial blog", "views": 0 }'/<code>
閱讀更多 JetQin90 的文章