ElasticSearch入门elasticsearch

ElasticSearch学习(二)--ElasticSearc

2018-08-07  本文已影响25人  荆辰曦

开始第一步

让我们建立一个员工目录

我们首先要做的是存储员工数据,每个文档(document)(行)代表一个员工。所以为了创建员工目录,我们将进行如下操作:

实际上这些都是很容易的,我们通过一个命令执行完成操作。

curl -XPUT "localhost:9200/megacorp/employee/1?pretty" -d '{
   "first_name":"John",
   "last_name":"Smith",
   "age":25,
   "about":"I love to go rock climbing",
   "interests":["sports","music"]
}'

注:在Windows下命令如下:

curl -H "application/json" -XPUT "localhost:9200/megacorp/employee/1?pretty" -d "{
  \ "first_name\":\"John\",
   \"last_name\":\"Smith\",
  \ "age\":25,
   \"about\":\"I love to go rock climbing\",
  \ "interests\":[\"sports\",\"music\"]
}"

自增ID

curl -XPOST "localhost:9200/website/blog/" -d '{
    "title" : "My first blog entry",
    "text" : "Just trying this out...",
    "date" : "2014/01/01"
}'

响应如下:

{
  "_index" : "website",
  "_type" : "blog",
  "_id" : "X7cGE2UB2XL2Aw5Pme58",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "failed" : 0
  },
  "_seq_no" : 0,
  "_primary_term" : 1
}

检索文档

curl -XGET "localhost:9200/website/blog/123?pretty"

响应如下:

{
  "_index" : "website",
  "_type" : "blog",
  "_id" : "123",
  "_version" : 1,
  "found" : true,
  "_source" : {
    "title" : "My first blog entry",
    "text" : "Just trying this out...",
    "date" : "2014/01/01"
  }
}

检索文档的一部分

通常,GET请求将返回文档的全部,存储在_source参数中。但是你可能感兴趣的字段只是title。请求个别字段可以使用_source参数。多个字段可以使用逗号分隔:

curl -i -XGET "localhost:9200/website/blog/123?_source=title,text&pretty"

_source字段现在只包含我们请求的字段,而且过滤了date字段:

HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 197

{
  "_index" : "website",
  "_type" : "blog",
  "_id" : "123",
  "_version" : 1,
  "found" : true,
  "_source" : {
    "text" : "Just trying this out...",
    "title" : "My first blog entry"
  }
}

或者你只想得到_source字段而不要其他的元数据,你可以这样请求:

curl -i -XGET "localhost:9200/website/blog/123/_source?pretty"

它仅仅返回:

HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 101

{
  "title" : "My first blog entry",
  "text" : "Just trying this out...",
  "date" : "2014/01/01"
}

检查文档是否存在

如果你想做的只是检查文档是否存在——-你对内容完全不感兴趣,那就使用HEAD方法代替GET,HEAD请求不会返回响应体。只有HTTP头:

curl -i -XHEAD "localhost:9200/website/blog/123?pretty"

ElasticSearch将会返回 200OK 状态(如果你的文档存在):

HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 224

如果不存在返回 404 Not Found:

HTTP/1.1 404 Not Found
content-type: application/json; charset=UTF-8
content-length: 83

当然,这只代表你在查询的那一刻文档不存在,但并不带表几毫秒后依旧不存在。另一进程在这期间可能创建新文档。

更新整个文档

文档在ElasticSearch中是不可变的——–我们不能修改他们。

curl -i -XPUT "localhost:9200/website/blog/123" -d '{
   "title":"My first blog entry",
   "text":"I am starting to get the hang of this...",
   "date":"2014/01/02"
}'

在响应中,我们可以看到ElasticSearch把_version增加了。

HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 223

{
  "_index" : "website",
  "_type" : "blog",
  "_id" : "123",
  "_version" : 2,
  "result" : "updated",
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}

在内部,ElasticSearch已经标记旧文档为删除并添加了一个完整的新文档。旧版本文档不会立即消失,但你也不能去访问它。ElasticSearch会在你继续索引更多数据时清理被删除的文档。

创建一个新文档

当索引一个文档,我们如何确定是完全创建了一个新的还是覆盖了一个已经存在的呢?
请记住_index,_type,_id三者唯一确定一个文档。所以要想保证文档是新加入的,最简单的方式是使用POST方法让ElasticSearch自动生成唯一_id

curl -i -XPOST "localhost:9200/website/blog/" -d '{
....
}'

然而,如果想使用自定义的_id,我们必须告诉ElasticSearch应该在_index,_type,_id三者不同时才接受请求。为了做到这点有两种方法,他们其实做的是同一件事。你可以选择适合自己的方式:
第一种方法使用 op_type 查询参数:

curl -XPUT "localhost:9200/website/blog/123?op_type=create" -d '{
    ........
}'

第二种方法是在URL后加 /_create 作为端点

curl -XPUT "localhost:9200/website/blog/123/_create" -d '{
    ........
}'

如果请求成功的创建了一个新文档,ElasticSearch将返回正常的元数据且响应状态吗是201 Created。

另一方面,如果包含相同的 _index,_type,_id的文档已经存在,ElasticSearch将返回409 Conflict响应状态码,错误信息如下

{
  "error" : {
    "root_cause" : [
      {
        "type" : "version_conflict_engine_exception",
        "reason" : "[blog][123]: version conflict, document already exists (current version [2])",
        "index_uuid" : "U3-JJt16SKmUn6rBuBDOfw",
        "shard" : "0",
        "index" : "website"
      }
    ],
    "type" : "version_conflict_engine_exception",
    "reason" : "[blog][123]: version conflict, document already exists (current version [2])",
    "index_uuid" : "U3-JJt16SKmUn6rBuBDOfw",
    "shard" : "0",
    "index" : "website"
  },
  "status" : 409
}

删除文档

删除文档的语法模式与之前基本一致,只不过要使用 DELETE 方法:

curl -XDELETE "localhost:9200/website/blog/123"

如果文档被找到,ElasticSearch将返回 200OK 状态码, _version 数字增加;如果文档未找到,我们将得到一个404 Not Found 状态码,尽管文档不存在,_version 依旧增加了,这是内部记录的一部分,它确保在多节点间不同操作可以有正确的顺序。

文档局部更新

最简单的 update 请求表单接受一个局部文档参数doc,它会合并到现有文档中------对象合并在一起,存在的标量字段被覆盖,新字段被添加。

curl -XPOST "localhost:9200/website/blog/1/_update" -d '{
     "doc":{
          "tags":["testing"],
          "views":0
      }
}'

如果请求成功,我们将看到类似请求的响应结果:

{
  "_index":"website",
  "_id":"1",
  "_type":"blog",
   "_version":3
}

检索文档显示被更新的_source字段:

{
   "_index":"website",
   "_id":"1",
   "_type":"blog",
   "_version":3
   "found":true,
   "_source":{
         "title":"My first blog entry",
         "text":"Starting to get the hang of this...",
          "tags":["testing"],
          "views":0
   }
}

我们新添加的字段已经被添加到_source字段中。

检索多个文档

ElasticSearch检索多个文档依旧非常快。合并多个请求可以避免每个请求单独的网络开销。如果你需要从ElasticSearch中检索多个文档,相对于一个一个的检索,更快的方式是在一个请求中使用multi-get或者mget API。

mget API参数是一个 docs 数组,数组的每个节点定义一个文档的 _index,_type,_id 元数据。如果你只想检索一个或几个确定的字段,也可以定义一个 _source 参数:

curl -i -XGET "localhost:9200/_mget" -d '{
    "docs":[
     {
         "_index":"megacorp",
         "_type":"employee",
         "_id":2
     },{
          "_index":"megacorp",
         "_type":"employee",
         "_id":3,
         "_source":"age"
     }
   ]

}'

响应体如下:

HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 545

{
  "docs" : [
    {
      "_index" : "megacorp",
      "_type" : "employee",
      "_id" : "2",
      "_version" : 2,
      "found" : true,
      "_source" : {
        "first_name" : "Douglas",
        "last_name" : "Fir",
        "age" : 35,
        "about" : "I like to build cabinets",
        "interests" : [
          "forestry"
        ]
      }
    },
    {
      "_index" : "megacorp",
      "_type" : "employee",
      "_id" : "3",
      "_version" : 1,
      "found" : true,
      "_source" : {
        "age" : 32
      }
    }
  ]
}

如果你想检索的文档在同一个 _index 中(甚至在同一个 _type 中),你就可以在URL中定义一个默认的 _index 或者 /_index/_type
你依旧可以在单独的请求中使用这些值:

curl -i -XGET "192.168.6.101:9200/megacorp/employee/_mget" -d '{
     "docs":[
          {"_id":2},
          {"_index":"website","_type":"blog","_id":123}
     ]
}'

结果如下:

HTTP/1.1 200 OK
content-type: application/json; charset=UTF-8
content-length: 655

{
  "docs" : [
    {
      "_index" : "megacorp",
      "_type" : "employee",
      "_id" : "2",
      "_version" : 2,
      "found" : true,
      "_source" : {
        "first_name" : "Douglas",
        "last_name" : "Fir",
        "age" : 35,
        "about" : "I like to build cabinets",
        "interests" : [
          "forestry"
        ]
      }
    },
    {
      "_index" : "website",
      "_type" : "blog",
      "_id" : "123",
      "_version" : 2,
      "found" : true,
      "_source" : {
        "title" : "My first blog entry",
        "text" : "I am starting to get the hang of this...",
        "date" : "2014/01/02"
      }
    }
  ]
}

事实上,如果所有文档具有相同的 _index_type,你可以通过简单的 ids 数组来代替完整的 docs 数组:

curl -i -XGET "192.168.6.101:9200/megacorp/employee/_mget" -d '{
  "ids":["2","3"]
}'

更省时的批量操作

就像 mget 允许我们一次性检索多个文档一样,bulk API允许我们使用单一请求来实现多个文档的create,index,delete,update操作。可以以成百上千的数据为一个批次按序进行操作。
bulk 的请求体如下所示,它有一点不同寻常。

{action : {metadata}}\n
{request  body}\n
{action:{metadata}}\n
{request body}\n
.........

这种格式类似于用"\n"符号连接起来的一行一行的JSON文档流,两个重要的点需要注意:

action/metadata定义了文档行为发生在了哪个文档之上。
行为(action)必须是以下几种:

行为 解释
create 当文档不存在时创建
index 创建新文档或替换已有文档
update 局部更新文档
delete 删除一个文档

在索引,更新,删除,创建一个文档时必须指定文档的_index,_type,_id这些元数据。
例如删除请求看起来像这样:

{"delete":{"_index":"megacorp","_type","employee","_id","2"}}

请求体(request body)由文档的 _source组成-------文档包含的一些字段以及其值。它被indexcreate操作所必须,这是有道理的:你必须提供文档用来索引。

{"create":{"_index":"website","_type":"blog","_id":"123"}}
{"title":"My first blog post"}

如果不定义_id,ID将会被自动创建:

{"index":{"_index":"website","_type":"blog"}}
{"title":"My second blog post"}

为了将这些放在一起,bulk 请求表单是这样的:

curl -i -XPOST "localhost:9200/_bulk" -d '
{"delete":{"_index":"website","_type":"blog","_id":"123"}}
{"create":{"_index":"website","_type":"blog","_id":"123"}}
{"title":"My first blog post"}
{"index":{"_index":"website","_type":"blog"}}
{"title":"My second blog post"}
{"update":{"_index":"website","_type":"blog","_id":"123","_retry_on_conflict":3}}
{"doc":{"title":"My update blog post"}}
'

你可以在同一个 index 下的同一个 type 里批量索引日志数据。为每个文档指定相同的元数据是多余的。就像 mget API,bulk 请求也可以在URL中使用 /_index/_index/_type

curl -i -XPOST "localhost:9200/website/_bulk" -d '
{"index":{"_type":"log"}}
{"event":"User logged in"}
'

你依旧可以覆盖元数据行的 _index_type,在没有覆盖时它会使用URL中的值作为默认值:

curl -i -XPOST "localhost:9200/website/log/_bulk" -d '
{"index":{}}
{"event":"User logged in"}
{"index":{"_type":"blog"}}
{"title":"Overriding the default type"}
'
上一篇下一篇

猜你喜欢

热点阅读