如何将 Elasticsearch 与流行的 Ruby 工具结合使用

173 阅读15分钟

作者:来自 Elastic  Fernando Briano

了解如何将 Elasticsearch 与一些流行的 Ruby 库一起使用。

在这篇博文中,我们将介绍如何将 Elasticsearch 与一些流行的 Ruby 工具结合使用。我们将实现 Ruby 客户端 “入门”指南 中介绍的常用 API。如果你点击该链接,你将看到如何使用官方 Elasticsearch 客户端:elasticsearch-ruby 运行这些相同的操作。

我们对客户端进行了广泛的测试,以确保 Elasticsearch 中的所有 API 都支持每个版本,包括当前正在开发的版本。这涵盖了近 500 个 API。

但是,在某些情况下,你可能不想使用客户端,而想在 Ruby 代码中自己实现一些功能。你的代码可能严重依赖于某个特定的库,并且你希望将其重用于 Elasticsearch。你可能在只需要几个 API 的设置中工作,并且不想引入新的依赖项。或者你的资源有限,并且你不想使用可以在 Elasticsearch 中完成所有操作的成熟客户端。

无论出于何种原因,Elasticsearch 都通过公开可直接调用的 REST API 简化了操作,因此你可以通过发出 HTTP 请求来访问其功能,而无需客户端。使用 API 时,建议查看 API 约定常用选项

简介

这些示例中使用的库是 Net::HTTP、HTTParty、exon、HTTP(又名 http.rb)、Faraday 和 elastic-transport。除了了解如何从 Ruby 与 Elasticsearch 交互之外,本文还将简要介绍每个库,让我们了解它们以及如何使用它们。本文不会深入介绍任何库,但会让你了解每个库的使用方式。

代码是在 Ruby 3.3.5 中编写和测试的。每个工具的版本将在各自的部分中提及。示例使用 require 'bundler/inline' 以方便在编写代码的同一文件中安装必要的 gem,但你也可以使用 Gemfile。

设置

在处理这些示例时,我使用 start-local,这是一个简单的 shell 脚本,可在几秒钟内设置 Elasticsearch 和 Kibana 以进行本地开发。在我编写此代码的目录中,我运行:

curl -fsSL https://elastic.co/start-local | sh

这将创建一个名为 elastic-start-local 的子目录,其中包含一个 .env 文件,其中包含我们连接和验证 Elasticsearch 所需的信息。我们可以在运行 Ruby 代码之前运行 source elastic-start-local/.env,也可以使用 dotenv gem:



1.  require 'dotenv'
2.  Dotenv.load('./elastic-start-local/.env')


以下代码示例假设此文件中的 ENV 变量已加载。

我们可以使用基本身份验证或 API 密钥身份验证对 Elasticsearch 进行身份验证。要使用基本身份验证,我们必须使用用户名 “elastic” 和存储在 ES_LOCAL_PASSWORD 中的值作为密码。要使用 API 密钥身份验证,我们需要此 .env 文件中存储在 ES_LOCAL_API_KEY 中的值。可以使用 Kibana 管理 Elasticsearch,它将使用 start-local 在 http://localhost:5601 运行,你也可以在 Kibana 中手动创建 API 密钥。

默认情况下,Elasticsearch 将在 http://localhost:9200 上运行,但示例从 ES_LOCAL_URL 环境变量加载主机。

你还可以使用任何其他 Elasticsearch 集群来运行这些集群,并相应地调整主机和凭据。如果你使用的是 start-local,你可以使用命令 docker compose stop 停止正在运行的 Elasticsearch 实例,然后从 elastic-start-local 目录使用 docker compose up 重新启动它。

Net::HTTP

Net::HTTP 提供了一个丰富的库,它使用 HTTP 请求-响应协议在客户端-服务器模型中实现客户端。我们可以在代码中使用 require 'net-http' 来要求这个库,然后开始使用它,而无需安装任何额外的依赖项。它不是最用户友好的,但它在 Ruby 中是原生可用的。这些示例中使用的版本是 0.4.1。



1.  require 'json'
2.  require 'net/http'

4.  host = URI(ENV['ES_LOCAL_URL'])
5.  headers = {
6.    'Authorization' => "ApiKey #{ENV['ES_LOCAL_API_KEY']}",
7.    'Content-Type' => 'application/json'
8.  }


这为我们提供了执行对 Elasticsearch 的请求的设置。我们可以通过对服务器根路径的初始请求来测试这一点:



1.  response = JSON.parse(Net::HTTP.get(host, headers))
2.  puts response
3.  # {"name"=>"b3349dfab89f", "cluster_name"=>"docker-cluster", ..., "tagline"=>"You Know, for Search"}


我们可以检查响应以获取更多信息:



1.  response = Net::HTTP.get_response(host, headers)
2.  puts "Content-Type: #{response['Content-type']}"
3.  puts "Response status: #{response.code}"
4.  puts "Body: #{JSON.parse(response.body)}"
5.  # Content-Type: application/json
6.  # Response status: 200
7.  # Body: {"name"=>"b3349dfab89f", ...


我们现在可以尝试创建一个索引



1.  index = 'nethttp_docs'
2.  http = Net::HTTP.new(host.hostname, host.port)

4.  # Create an index
5.  response = http.put("/#{index}", '', headers)
6.  puts response
7.  # {"acknowledged":true,"shards_acknowledged":true,"index":"nethttp_index"}


有了索引,我们现在就可以开始处理文档了。



1.  # Index a document
2.  document = { name: 'elasticsearch-ruby', description: 'Official Elasticsearch Ruby client' }.to_json
3.  response = http.post("/#{index}/_doc", document, headers)
4.  puts response
5.  # {"_index":"nethttp_docs","_id":"...

7.  # Save the id for following requests:
8.  id = JSON.parse(response.body)["_id"]


请注意,我们需要将文档转换为 JSON 才能在请求中使用它。有了索引文档,我们可以测试一个非常简单的 search 请求:



1.  # Search
2.  search_body = { query: { match_all: {} } }.to_json
3.  response = http.post("#{index}/_search", search_body, headers)
4.  JSON.parse(response.body)['hits']['hits']
5.  # => [{"_index"=>"nethttp_docs", "_id"=>...

并对索引数据进行更多工作:



1.  # Get a document
2.  response = http.get("#{index}/_doc/#{id}", headers)
3.  JSON.parse(response.body)
4.  # => {"_index"=>"nethttp_docs", ..., "_source"=>{"name"=>"elasticsearch-ruby", "description"=>"Official Ruby client"}}

6.  # Update a document
7.  document = { doc: { name: 'net-http-ruby', description: 'NetHTTP Ruby client' } }.to_json
8.  response = http.post("#{index}/_update/#{id}", document, headers)
9.  # => <Net::HTTPOK 200 OK readbody=true>

11.  # Deleting documents
12.  response = http.delete("#{index}/_doc/#{id}", headers)
13.  # => <Net::HTTPOK 200 OK readbody=true>


最后,我们将删除索引来清理集群:



1.  # Deleting an index
2.  response = http.delete(index, headers)
3.  # => <Net::HTTPOK 200 OK readbody=true>


HTTParty

HTTParty 是一款 “旨在让 HTTP 变得有趣” 的瑰宝。它提供了一些有用的抽象来发出请求和处理响应。这些示例使用了该库的 0.22.0 版本。



1.  require 'bundler/inline'
2.  require 'json'

4.  gemfile do
5.    source 'https://rubygems.org'
6.    gem 'httparty'
7.  end

9.  host = URI(ENV['ES_LOCAL_URL'])
10.  headers = {
11.    'Authorization' => "ApiKey #{ENV['ES_LOCAL_API_KEY']}",
12.    'Content-Type' => 'application/json'
13.  }


向服务器发出的初始请求:



1.  response = HTTParty.get(host, headers: headers)
2.  # => {"name"=>"b3349dfab89f",
3.  ...

5.  # And we can see more info:
6.  response.headers['content-type']
7.  # => "application/json"
8.  response.code
9.  # => 200
10.  JSON.parse(response.body)
11.  # => {"name"=>"b3349dfab89f", ...


如果响应内容类型为 application/json,HTTParty 将解析响应并返回 Ruby 对象(例如哈希或数组)。解析 JSON 的默认行为将以字符串形式返回键。我们可以按如下方式使用响应:



1.  response
2.  # =>
3.  # {"name"=>"b3349dfab89f",
4.  #  "cluster_name"=>"docker-cluster",
5.  #  ...
6.  #  "tagline"=>"You Know, for Search"}

8.  JSON.parse(response.body, symbolize_names: true)
9.  #  =>
10.  # {:,
11.  #  :cluster_,
12.  #  ...
13.  #  :tagline=>"You Know, for Search"}

15.  # We can also access the response keys directly, like the Elasticsearch::API:Response object returned by the Elasticsearch Ruby client:
16.  response['name']
17.  # => "b3349dfab89f"


README 展示了如何使用类方法快速发出请求以及创建自定义类的选项。实现 Elasticsearch Client 类并添加我们想要使用的不同 API 方法会更方便。例如:



1.  class ESClient
2.    include HTTParty
3.    base_uri ENV['ES_LOCAL_URL']

5.    def initialize
6.      @headers = {
7.        'Authorization' => "ApiKey #{ENV['ES_LOCAL_API_KEY']}",
8.        'Content-Type' => 'application/json'
9.      }
10.    end

12.    def info
13.      self.class.get('/', headers: @headers)
14.    end
15.  end

17.  client = ESClient.new
18.  puts client.info


我们不想在这篇博文中使用 HTTParty 重新实现 Elasticsearch Ruby,但当仅使用一些 API 时,这可能是一种替代方案。我们将了解如何构建其余请求:



1.  index = 'httparty-test'
2.  # Create an index
3.  response = HTTParty.put("#{host}/#{index}", headers: headers)
4.  puts response
5.  # {"acknowledged"=>true, "shards_acknowledged"=>true, "index"=>"httparty-test"}

7.  # Index a Document
8.  document = { name: 'elasticsearch-ruby', description: 'Official Elasticsearch Ruby client' }.to_json
9.  response = HTTParty.post("#{host}/#{index}/_doc", body: document, headers: headers)
10.  # => {"_index"=>"httparty-test", "_id": ... }

12.  # Save the id for following requests:
13.  id = response["_id"]

15.  # Get a document:
16.  response = HTTParty.get("#{host}/#{index}/_doc/#{id}", headers: headers)
17.  # => {"_index"=>"httparty-test", ..., "_source"=>{"name"=>"elasticsearch-ruby", "description"=>"Official Elasticsearch Ruby client"}}

19.  # Search
20.  search_body = { query: { match_all: {} } }.to_json
21.  response = HTTParty.post("#{host}/#{index}/_search", body: search_body, headers: headers)
22.  response['hits']['hits']
23.  # => [{"_index"=>"httparty-test", ... ,"_source"=>{"name"=>"elasticsearch-ruby", "description"=>"Official Elasticsearch Ruby client"}}]

25.  # Update a document
26.  document = { doc: { name: 'httparty-ruby', description: 'HTTParty Elasticsearch client' } }.to_json
27.  response = HTTParty.post("#{host}/#{index}/_update/#{id}", body: document, headers: headers)
28.  # => {"_index"=>"httparty-test", "_id" ... }
29.  response.code
30.  # => 200

32.  # Deleting documents
33.  response = HTTParty.delete("#{host}/#{index}/_doc/#{id}", headers: headers)
34.  # => {"_index"=>"httparty-test", "_id" ... }
35.  response.code
36.  # => 200

38.  # Deleting an index
39.  response = HTTParty.delete("#{host}/#{index}", headers: headers)
40.  # => {"acknowledged":true}


excon

Excon 的设计目标是简单、快速和高性能。它特别适合在 API 客户端中使用,因此非常适合与 Elasticsearch 交互。此代码使用 Excon 版本 0.111.0。



1.  require 'bundler/inline'
2.  require 'json'
3.  gemfile do
4.    source 'https://rubygems.org'
5.    gem 'excon'
6.  end

8.  host = URI(ENV['ES_LOCAL_URL'])
9.  headers = {
10.    'Authorization' => "ApiKey #{ENV['ES_LOCAL_API_KEY']}",
11.    'Content-Type' => 'application/json'
12.  }

14.  response = Excon.get(host, headers: headers)
15.  puts "Content-Type: #{response.headers['content-type']}"
16.  puts "Response status: #{response.status}"
17.  puts "Body: #{JSON.parse(response.body)}"
18.  # Content-Type: application/json
19.  # Response status: 200
20.  # Body: {"name"=>"b3349dfab89f", "cluster_name"=>"docker-cluster", ..., "tagline"=>"You Know, for Search"}


Excon 请求返回一个 Excon::Response 对象,该对象具有 body、headers、remote_ip 和 status 属性。我们还可以使用键作为符号直接访问数据,类似于 Elasticsearch::API::Response 的工作方式:



1.  response[:headers]
2.  # => {"X-elastic-product"=>"Elasticsearch", "content-type"=>"application/json", "content-length"=>"541"}


我们可以在多个请求之间重复使用一个连接,以共享选项并提高性能。我们还可以使用持久连接与初始请求建立套接字连接,并在运行以下示例时保持套接字打开:



1.  connection = Excon.new(host, persistent: true, headers: headers)
2.  index = 'excon-test'

4.  # Create an index
5.  response = connection.put(path: index)
6.  puts response.body
7.  # {"acknowledged":true,"shards_acknowledged":true,"index":"excon-test"}

9.  # Index a Document
10.  document = { name: 'elasticsearch-ruby', description: 'Official Elasticsearch Ruby client' }.to_json
11.  response = connection.post(path: "#{index}/_doc", body: document)
12.  puts response.body
13.  # {"_index":"excon-test","_id" ... }

15.  # Save the id for following requests:
16.  id = JSON.parse(response.body)["_id"]

18.  # Get a document:
19.  response = connection.get(path: "#{index}/_doc/#{id}")
20.  JSON.parse(response.body)
21.  # => {"_index"=>"excon-test", ...,"_source"=>{"name"=>"elasticsearch-ruby", "description"=>"Official Elasticsearch Ruby client"}}

23.  # Search
24.  search_body = { query: { match_all: {} } }.to_json
25.  response = connection.post(path: "#{index}/_search", body: search_body)
26.  JSON.parse(response.body)['hits']['hits']
27.  # => [{"_index"=>"excon-test",..., "_source"=>{"name"=>"elasticsearch-ruby", "description"=>"Official Elasticsearch Ruby client"}}]

29.  # Update a document
30.  document = { doc: { name: 'excon-ruby', description: 'Excon Elasticsearch client' } }.to_json
31.  response = connection.post(path: "#{index}/_update/#{id}", body: document)
32.  # => <Excon::Response:0x0000...
33.  response.status
34.  # => 200

36.  # Deleting documents
37.  response = connection.delete(path: "#{index}/_doc/#{id}")
38.  # => <Excon::Response:0x0000...
39.  response.status
40.  # => 200

42.  # Deleting an index
43.  response = connection.delete(path: index)
44.  puts response.body
45.  # {"acknowledged":true}

47.  # Close connection
48.  connection.reset


HTTP (http.rb)

HTTP 是一个 HTTP 客户端,它使用类似于 Python 的 Requests 的可链接 API。它用 Ruby 实现 HTTP 协议,并将解析外包给本机扩展。此代码中使用的版本是 5.2.0。



1.  host = URI(ENV['ES_LOCAL_URL'])

3.  headers = {
4.    'Authorization' => "ApiKey #{ENV['ES_LOCAL_API_KEY']}",
5.    'Content-Type' => 'application/json'
6.  }

8.  HTTP.get(host, headers: headers)
9.  response = HTTP.get(host, headers: headers)
10.  # => <HTTP::Response/1.1 200 OK {"X-elastic-product"=>"Elasticsearch", "content-type"=>"application/json", "content-length"=>"541"}>
11.  puts "Content-Type: #{response.headers['content-type']}"
12.  puts "Response status: #{response.code}"
13.  puts "Body: #{JSON.parse(response.body)}"
14.  # Content-Type: application/json
15.  # Response status: 200
16.  # Body: {"name"=>"b3349dfab89f", ..., "tagline"=>"You Know, for Search"}


我们还可以使用 auth 方法来利用可链接 API:

HTTP.auth(headers["Authorization"]).get(host)

或者因为我们还关心内容类型标头、链 headers:

HTTP.headers(headers).get(host)

因此,一旦我们创建了持久客户端,构建请求就会变得更短:



1.  # Create an index
2.  index = 'http-test'
3.  response = http.put("#{host}/#{index}")
4.  response.parse
5.  # => {"acknowledged"=>true, "shards_acknowledged"=>true, "index"=>"http-test"}

7.  # Index a Document
8.  document = { name: 'elasticsearch-ruby', description: 'Official Elasticsearch Ruby client' }.to_json
9.  response = http.post("#{host}/#{index}/_doc", body: document)
10.  # => <HTTP::Response/1.1 201 Created {"Location"=>"/http-test/_doc/GCA1KZIBr7n-DzjRAVLZ", "X-elastic-product"=>"Elasticsearch", "content-type"=>"application/json", "content-length"=>"161"}>
11.  response.parse
12.  # => {"_index"=>"http-test", "_id" ...}

14.  # Save the id for following requests:
15.  id = response.parse['_id']

17.  # Get a document:
18.  response = http.get("#{host}/#{index}/_doc/#{id}")
19.  # => <HTTP::Response/1.1 200 OK {"X-elastic-product"=>"Elasticsearch", "content-type"=>"application/json", "content-length"=>"198"}>
20.  response.parse
21.  # => {"_index"=>"http-test", "_id", ..., "_source"=>{"name"=>"elasticsearch-ruby", "description"=>"Official Elasticsearch Ruby client"}}

23.  # Search
24.  search_body = { query: { match_all: {} } }.to_json
25.  response = http.post("#{host}/#{index}/_search", body: search_body)
26.  # => <HTTP::Response/1.1 200 OK ...
27.  response.parse['hits']['hits']
28.  # => [{"_index"=>"http-test", "_id",..., "_source"=>{"name"=>"elasticsearch-ruby", "description"=>"Official Elasticsearch Ruby client"}}]

30.  # Update a document
31.  document = { doc: { name: 'http-ruby', description: 'HTTP Elasticsearch client' } }.to_json
32.  response = http.post("#{host}/#{index}/_update/#{id}", body: document)
33.  # => <HTTP::Response/1.1 200 OK ...
34.  response.code
35.  # => 200
36.  response.flush

38.  # Deleting documents
39.  response = http.delete("#{host}/#{index}/_doc/#{id}")
40.  # => <HTTP::Response/1.1 200 OK ...
41.  response.code
42.  # => 200
43.  response.flush

45.  # Deleting an index
46.  response = http.delete("#{host}/#{index}")
47.  # => <HTTP::Response/1.1 200 OK ...
48.  response.parse
49.  # => {"acknowledged"=>true}


文档警告我们,在持久连接中发送下一个请求之前,必须使用响应。这意味着在响应对象上调用 to_s、parse 或 flush。

Faraday

Faraday 是 Elasticsearch 客户端默认使用的 HTTP 客户端库。它提供了多个适配器的通用接口,你可以在实例化客户端时选择这些适配器(Net::HTTP、Typhoeus、Patron、Excon 等)。此代码中使用的 Faraday 版本为 2.12.0。

get 的签名为 (url, params = nil, headers = nil),因此我们在此初始测试请求中传递 nil 作为参数:



1.  require 'bundler/inline'
2.  require 'json'
3.  gemfile do
4.    source 'https://rubygems.org'
5.    gem 'faraday'
6.  end

8.  response = Faraday.get(host, nil, headers)
9.  # => <Faraday::Response:0x0000...


响应是一个 Faraday::Response 对象,其中包含响应状态、标头和正文,我们还可以访问 Faraday Env 对象中的许多属性。正如我们在其他库中看到的那样,在我们的用例中使用 Faraday 的推荐方法是创建一个 Faraday::Connection 对象:



1.  conn = Faraday.new(
2.    url: host,
3.    headers: headers
4.  )

6.  response = conn.get('/')
7.  puts "Content-Type: #{response.headers['content-type']}"
8.  puts "Response status: #{response.code}"
9.  puts "Body: #{JSON.parse(response.body)}"
10.  # Content-Type: application/json
11.  # Response status: 200
12.  # Body: {"name"=>"b3349dfab89f", ..., "tagline"=>"You Know, for Search"}


现在重新使用该连接,我们可以看到 Faraday 的其余请求是什么样的:



1.  index = 'faraday-test'
2.  # Create an index
3.  response = conn.put(index)
4.  puts response.body
5.  # {"acknowledged":true,"shards_acknowledged":true,"index":"faraday-test"}'

7.  # Index a Document
8.  document = { name: 'elasticsearch-ruby', description: 'Official Elasticsearch Ruby client' }.to_json
9.  # The signature for post is (url, body = nil, headers = nil), unlike the get signature:
10.  response = conn.post("#{index}/_doc", document)
11.  puts response.body
12.  # {"_index":"faraday-test","_id" ... }

14.  # Save the id for following requests:
15.  id = JSON.parse(response.body)["_id"]

17.  # Get a document:
18.  response = conn.get("#{index}/_doc/#{id}")
19.  JSON.parse(response.body)
20.  # => {"_index"=>"faraday-test", ...,"_source"=>{"name"=>"elasticsearch-ruby", "description"=>"Official Elasticsearch Ruby client"}}

22.  # Search
23.  search_body = { query: { match_all: {} } }.to_json
24.  response = conn.post("#{index}/_search", search_body)
25.  JSON.parse(response.body)['hits']['hits']
26.  # => [{"_index"=>"faraday-test", ..., "_source"=>{"name"=>"elasticsearch-ruby", "description"=>"Official Elasticsearch Ruby client"}}]

28.  # Update a document
29.  document = { doc: { name: 'faraday-ruby', description: 'Faraday client' } }.to_json
30.  response = conn.post("#{index}/_update/#{id}", document)
31.  # => <Faraday::Response:0x0000...
32.  response.status
33.  # => 200

35.  # Deleting documents
36.  response = conn.delete("#{index}/_doc/#{id}")
37.  # => <Excon::Response:0x0000...
38.  response.status
39.  # => 200

41.  # Deleting an index
42.  response = conn.delete(index)
43.  puts response.body
44.  # {"acknowledged":true}


Elastic Transport

elastic-transport 库是 Ruby 中的精华,用于在官方 Elastic Ruby 客户端中执行 HTTP 请求、编码、压缩等。多年来,这个库已经针对每个官方版本的 Elasticsearch 进行了实战测试。它曾被称为 elasticsearch-transport,因为它是官方 Elasticsearch 客户端的基础。然而,在客户端的 8.0.0 版本中,我们将传输库迁移到了 elastic-transport,因为它还支持官方企业搜索客户端和最近的 Elasticsearch 无服务器(severless)客户端。

它默认使用 Faraday 实现,支持我们之前看到的几种不同的适配器。你还可以使用库中包含的 Manticore 和 Curb(libcurl 的 Ruby 绑定)实现。你甚至可以编写自己的实现,或者使用我们在这里介绍的一些库编写实现。但这将是另一篇博客文章的主题!

Elastic Transport 还可以用作与 Elasticsearch 交互的 HTTP 库。它将处理你需要的一切,并且具有许多与 Elastic 使用相关的设置和不同配置。这里使用的版本是最新的8.3.5。一个简单的例子:



1.  require 'bundler/inline'

3.  gemfile do
4.    source 'https://rubygems.org'
5.    gem 'elastic-transport'
6.  end

8.  host = URI(ENV['ES_LOCAL_URL'])
9.  headers = { 'Authorization' => "ApiKey #{ENV['ES_LOCAL_API_KEY']}" }

11.  # Instantiate a new Transport client
12.  transport = Elastic::Transport::Client.new(hosts: host)

14.  # Make a request to the root path ('info') to make sure we can connect:
15.  response = transport.perform_request('GET', '/', {}, nil, headers)

17.  # Create an index
18.  index = 'elastic-transport_docs'
19.  response = transport.perform_request('PUT', "/#{index}", {}, nil, headers)
20.  response.body
21.  # => {"acknowledged"=>true, "shards_acknowledged"=>true, "index"=>"elastic-transport_docs"}

23.  # Index a document
24.  document = { name: 'elastic-transport', description: 'Official Elastic Ruby HTTP transport layer' }.to_json
25.  response = transport.perform_request('POST', "/#{index}/_doc", {}, document, headers)
26.  response.body
27.  # => {"_index"=>"elastic-transport_docs", "_id"=> ... }

29.  # Get the document we just indexed
30.  id = response.body['_id']
31.  response = transport.perform_request('GET', "/#{index}/_doc/#{id}", {}, nil, headers)
32.  response.body['_source']
33.  # => {"name"=>"elastic-transport", "description"=>"Official Elastic Ruby HTTP transport layer"}

35.  # Search for a document
36.  search_body = { query: { match_all: {} } }
37.  response = transport.perform_request('POST', "/#{index}/_search", {}, search_body, headers)
38.  response.body.dig('hits', 'hits').first
39.  # => {"_index"=>"elastic-transport_docs", ..., "_source"=>{"name"=>"elastic-transport", "description"=>"Official Elastic Ruby HTTP transport layer"}}

41.  # Update the document
42.  body = { doc: { name: 'elastic-transport', description: 'Official Elastic Ruby HTTP transport layer.' } }.to_json
43.  response = transport.perform_request('POST', "/#{index}/_update/#{id}", {}, body, headers)
44.  response.body
45.  # => {"_index"=>"elastic-transport_docs", ... }

47.  # Delete a document
48.  response = transport.perform_request('DELETE', "/#{index}/_doc/#{id}", {}, nil, headers)
49.  response.body
50.  # => {"_index"=>"elastic-transport_docs", ... }


结论

如你所见,Elasticsearch Ruby 客户端做了很多工作,让你可以轻松地在 Ruby 代码中与 Elasticsearch 交互。在这篇博文中,我们甚至没有深入讨论如何处理更复杂的请求或处理错误。但 Elasticsearch 的 REST API 使其可以与任何支持 HTTP 请求的库一起使用,无论是 Ruby 还是其他任何语言。Elasticsearch REST API 指南是了解可用 API 及其使用方法的绝佳参考。

准备好自己尝试一下了吗?开始免费试用

想要获得 Elastic 认证?了解下一期 Elasticsearch 工程师培训何时举行!

原文:How to use Elasticsearch with popular Ruby tools - Search Labs