シリーズトップページ |
---|
https://qiita.com/robozushi10/items/2c8b6951ee342b013974 |
[017] ドキュメントの検索結果と該当件数の表示をする by Ruby elasticsearch 7.14
概要
Ruby の Elasticsearch Client を使って Elasticsearch 7.14 で REST API の操作する.
また、比較のために、Kibana DevTool でのクエリも合せて記しておく.
今回はインデックス「shakespeare」から次の「ドキュメントの検索」と「件数表示」をする.
以下2つを全て満たすドキュメントを抽出し、件数を表示させる.
・フィルード「text_entry」の値に「ACT」という単語を含む
・フィルード「text_entry」の値に「V」という単語を含む
ただし、ここでも Elasticsearch デフォルト挙動の 10件しか取り出さないものとする.
検証環境
下記の要領で検証用データ「Shakespeare」が登録された
・Elasticsearch + Kibana (7.14)
を使用した
[00] Ruby の elasticsearch client パッケージを使って Elasticsearch 7.14 を操作してみる ... 検証環境構築編
参考にした情報
URL |
---|
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-search.html |
実践
Kibana DevTool の場合
コード
・agg
(aggregation
) という検索結果に対して計算をする機能を使う.
・下記「docs_aggs
」は任意の名称で良い
・下記「field
」の「text_entry
」はフィールド名である
GET shakespeare/_search
{
"query": {
"query_string": {
"query": "text_entry:ACT AND text_entry:V"
}
},
"aggs": {
"docs_aggs": {
"terms": {
"field": "text_entry.keyword",
"size": 2560
}
}
}
}
結果
Ruby の場合
コード
重要な部分は「if __FILE__ == $0 以降
」である.
class MySimpleClient は丸々コピーで良い. (が、192.168.10.115 のみ、適宜読み替えること)
#!/usr/bin/env ruby
# -*- encoding: utf-8 -*-
require 'multi_json'
require 'faraday'
require 'elasticsearch/api'
require 'active_support/core_ext' #! note_0004
require 'active_support' #! note_0005
class MySimpleClient
# note_0001
include Elasticsearch::API
CONNECTION = ::Faraday::Connection.new url: 'http://192.168.10.115:29200'
def perform_request(method, path, params, body, headers = nil)
#! note_0003
CONNECTION.run_request \
method.downcase.to_sym,
path_with_params(path, params),
(body ? MultiJson.dump(body): nil),
{'Content-Type' => 'application/json'}
end
private
def path_with_params(path, params)
return path if params.blank?
case params
when String
"#{path}?#{params}"
when Hash
"#{path}?#{params.to_query}"
else
raise ArgumentError, "Cannot parse params: '#{params}'"
end
end
end
if __FILE__ == $0
client = MySimpleClient.new
q = {
"query": {
# note_0006
"query_string": {
"query": "text_entry:ACT AND text_entry:V"
}
},
"aggs": {
"docs_aggs": {
"terms": {
"field": "text_entry.keyword",
"size": 2560
}
}
}
}
res = client.search index: 'shakespeare', body: q
h = JSON.parse(res)
pp h
end
# note_0001: https://rubydoc.info/gems/elasticsearch-api
# note_0002: https://rubydoc.info/gems/elasticsearch-api/Elasticsearch/API/Cluster/Actions#health-instance_method
# note_0003: client.cluster.health から呼び出されるので実装が必要である
# note_0004: 'active_support' を 'active_support/core_ext' に変更する.
# APIドキュメントにある 'active_support' 指定だと次のエラーが発生してしまうためである.
# tutorial.rb:26:in `path_with_params': undefined method `blank?' for {}:Hash (NoMethodError)
# note_0005: require 'active_support' が存在しないと次のエラーが発生してしまう.
# /usr/local/bundle/gems/activesupport-6.0.4/lib/active_support/core_ext/object/json.rb:42:
# in `to_json': uninitialized constant ActiveSupport::JSON (NameError)
# note_0006: mapping は次の通り
# {"shakespeare"=>
# {"mappings"=>
# {"properties"=>
# {"line_id"=>{"type"=>"long"},
# "line_number"=>
# {"type"=>"text",
# "fields"=>{"keyword"=>{"type"=>"keyword", "ignore_above"=>256}}},
# "play_name"=>
# {"type"=>"text",
# "fields"=>{"keyword"=>{"type"=>"keyword", "ignore_above"=>256}}},
# "speaker"=>
# {"type"=>"text",
# "fields"=>{"keyword"=>{"type"=>"keyword", "ignore_above"=>256}}},
# "speech_number"=>
# {"type"=>"text",
# "fields"=>{"keyword"=>{"type"=>"keyword", "ignore_above"=>256}}},
# "text_entry"=>
# {"type"=>"text",
# "fields"=>{"keyword"=>{"type"=>"keyword", "ignore_above"=>256}}},
# "type"=>
# {"type"=>"text",
# "fields"=>{"keyword"=>{"type"=>"keyword", "ignore_above"=>256}}}}}}}
結果
下記の 🛑} より、36件と表示されている.
略
{"type"=>"act",
"line_id"=>24007,
"play_name"=>"A Comedy of Errors",
"speech_number"=>87,
"line_number"=>"",
"speaker"=>"OF SYRACUSE",
"text_entry"=>"ACT V"}},
{"_index"=>"shakespeare",
"_type"=>"_doc",
"_id"=>"27743",
"_score"=>18.431282,
"_source"=>
{"type"=>"act",
"line_id"=>27744,
"play_name"=>"Coriolanus",
"speech_number"=>7,
"line_number"=>"",
"speaker"=>"AUFIDIUS",
"text_entry"=>"ACT V"}},
{"_index"=>"shakespeare",
"_type"=>"_doc",
"_id"=>"31443",
"_score"=>18.431282,
"_source"=>
{"type"=>"act",
"line_id"=>31444,
"play_name"=>"Cymbeline",
"speech_number"=>13,
"line_number"=>"",
"speaker"=>"BELARIUS",
"text_entry"=>"ACT V"}}]},
"aggregations"=>
{"docs_aggs"=>
{"doc_count_error_upper_bound"=>0,
"sum_other_doc_count"=>0,
"buckets"=>[{"key"=>"ACT V", "doc_count"=>36🛑}]}}}
検証
結果比較 DevTool vs Ruby が一致しているか?
🆗一致している模様