elasticsearch-explain-response 0.0.5 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ade43ddb3bce35fbc76c2f90457646665448a66a
4
- data.tar.gz: 58d5df58953bad1dade17dce95826f923a85ebd7
3
+ metadata.gz: a45d429446a768356511e49f49519a4b59c82bb1
4
+ data.tar.gz: cae5a22110b309224a5ad2ae74c4f1e8a0616852
5
5
  SHA512:
6
- metadata.gz: c65535f7eb7d273fc89e41923eee15fc9a3d265e538f70d1c13baed4238365c513e780143518d33cf457923bede9cbee000cdf9e1727df1272a0750f84bac2b8
7
- data.tar.gz: c89b690ab7dea90299acba77b7a60717029d42452271d5b1ff41fd178ec9fd5a77262590ee3eb6b9782918e66eb9d796f89c183b925cca0b96a06e4b2004f9d6
6
+ metadata.gz: 37cdde1a62667643d3e0d137457e8890251e727ba51865ac8eaf97af61ac203d66cb5c646569557e9f16eb4c784a1dc0a4297340e4327ef605f0f0904f1d927d
7
+ data.tar.gz: 085fa522790f416383bed3f13c699c8c38f2f640d81a02b8948d0e022f7c2d067e052c301a20b5b72835473fa606790bb55a29c53dc317789fa1862723fd2242
data/README.md CHANGED
@@ -5,7 +5,7 @@
5
5
  Parse Elasticsearch Explain Response and summarize it in a simple way.
6
6
  This gem is intended for developers working with Elasticsearch to debug search scores
7
7
  in a easier way.
8
- The current feature is very simple, but any sugguestions or feature requests are welcomed.
8
+ The current feature is very simple, but any suggestions or feature requests are welcomed.
9
9
 
10
10
  ## Installation
11
11
 
@@ -17,41 +17,45 @@ gem 'elasticsearch-explain-response'
17
17
 
18
18
  And then execute:
19
19
 
20
- $ bundle
20
+ ```
21
+ $ bundle
22
+ ```
21
23
 
22
24
  Or install it yourself as:
23
25
 
24
- $ gem install elasticsearch-explain-response
26
+ ```
27
+ $ gem install elasticsearch-explain-response
28
+ ```
25
29
 
26
30
  ## Usage
27
31
 
28
32
  ### Summarize the explanation in one line
29
33
 
30
- ```
31
- require 'elasticsearch'
32
- client = Elasticsearch::Client.new
33
- result = client.explain index: "megacorp", type: "employee", id: "1", q: "last_name:Smith"
34
- puts Elasticsearch::API::Response::ExplainResponse.new(result["explanation"]).render_in_line
35
- #=>
36
- 1.0 = (1.0(termFreq=1.0)) x 1.0(idf(2/3)) x 1.0(fieldNorm)
37
- ```
34
+ ```ruby
35
+ require 'elasticsearch'
36
+ client = Elasticsearch::Client.new
37
+ result = client.explain index: "megacorp", type: "employee", id: "1", q: "last_name:Smith"
38
+ puts Elasticsearch::API::Response::ExplainResponse.new(result["explanation"]).render_in_line
39
+ #=>
40
+ 1.0 = (1.0(termFreq=1.0)) x 1.0(idf(2/3)) x 1.0(fieldNorm)
41
+ ```
38
42
 
39
43
  ### Summarize the explanation in lines
40
44
 
41
- ```
42
- require 'elasticsearch'
43
- client = Elasticsearch::Client.new
44
- result = client.explain index: "megacorp", type: "employee", id: "1", q: "last_name:Smith"
45
- puts Elasticsearch::API::Response::ExplainResponse.new(result["explanation"]).render
46
- #=>
47
- 1.0 = 1.0(fieldWeight)
48
- 1.0 = 1.0(tf(1.0)) x 1.0(idf(2/3)) x 1.0(fieldNorm)
49
- 1.0 = 1.0(termFreq=1.0)
50
- ```
45
+ ```ruby
46
+ require 'elasticsearch'
47
+ client = Elasticsearch::Client.new
48
+ result = client.explain index: "megacorp", type: "employee", id: "1", q: "last_name:Smith"
49
+ puts Elasticsearch::API::Response::ExplainResponse.new(result["explanation"]).render
50
+ #=>
51
+ 1.0 = 1.0(fieldWeight)
52
+ 1.0 = 1.0(tf(1.0)) x 1.0(idf(2/3)) x 1.0(fieldNorm)
53
+ 1.0 = 1.0(termFreq=1.0)
54
+ ```
51
55
 
52
56
  ## Contributing
53
57
 
54
- 1. Fork it ( https://github.com/[my-github-username]/elasticsearch-explain-response/fork )
58
+ 1. Fork it ( https://github.com/tomoya55/elasticsearch-explain-response/fork )
55
59
  2. Create your feature branch (`git checkout -b my-new-feature`)
56
60
  3. Commit your changes (`git commit -am 'Add some feature'`)
57
61
  4. Push to the branch (`git push origin my-new-feature`)
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "elasticsearch-explain-response"
7
- spec.version = "0.0.5"
7
+ spec.version = "0.1.0"
8
8
  spec.authors = ["Tomoya Hirano"]
9
9
  spec.email = ["hiranotomoya@gmail.com"]
10
10
  spec.summary = %q{Parser for Elasticserach Explain response}
@@ -1,7 +1,11 @@
1
+ require "elasticsearch/api/response/string_helper"
2
+
1
3
  module Elasticsearch
2
4
  module API
3
5
  module Response
4
6
  class ExplainParser
7
+ include StringHelper
8
+
5
9
  def parse(explain_tree)
6
10
  root = create_node(explain_tree, level: 0)
7
11
  parse_details(root)
@@ -45,12 +49,15 @@ module Elasticsearch
45
49
  type = "score"
46
50
  operation = "score"
47
51
  operator = "x"
48
- when /\Amatch filter\: (?:cache\()?(?:(?<op>[\w]+)\()*(?<f>.+)\:(?<v>[^\)]+)\)*\z/
52
+ when /\Amatch filter\: (?:cache\()?(?:(?<op>[\w]+)\()*(?<c>.+)\)*\z/
49
53
  type = "match"
50
54
  operation = "match"
51
55
  operation += ".#{$~[:op]}" if $~[:op] && !%w[QueryWrapperFilter].include?($~[:op])
52
- field = $~[:f]
53
- value = $~[:v]
56
+ content = $~[:c]
57
+ content = content[0..-2] if content.end_with?(')')
58
+ hash = tokenize_contents(content)
59
+ field = hash.keys.join(", ")
60
+ value = hash.values.join(", ")
54
61
  when /\AFunction for field ([\w\_]+)\:\z/
55
62
  type = "func"
56
63
  operation = "func"
@@ -70,6 +77,15 @@ module Elasticsearch
70
77
  /\Afunction score\, score mode \[multiply\]\z/
71
78
  type = "func score"
72
79
  operator = "x"
80
+ when /\Ascript score function\, computed with script:\"(?<s>.+)\"\s*(?:and parameters:\s*(?<p>.+))?/m
81
+ type = "script"
82
+ operation = "script"
83
+ script, param = $~[:s], $~[:p]
84
+ script = script.gsub("\n", '')
85
+ script = "\"#{script}\""
86
+ param.gsub!("\n", '') if param
87
+ field = script.scan(/doc\[\'([\w\.]+)\'\]/).flatten.uniq.compact.join(" ")
88
+ value = [script, param].join(" ")
73
89
  when "static boost factor", "boostFactor"
74
90
  type = "boost"
75
91
  operation = "boost"
@@ -93,8 +109,6 @@ module Elasticsearch
93
109
  operation = description
94
110
  end
95
111
 
96
- # binding.pry if operator.nil?
97
-
98
112
  Description.new(
99
113
  raw: description,
100
114
  type: type,
@@ -10,6 +10,7 @@ module Elasticsearch
10
10
  disable_colorization if options[:colorize] == false
11
11
  @max = options[:max] || 3
12
12
  @plain_score = options[:plain_score] == true
13
+ @show_values = options[:show_values] == true
13
14
  end
14
15
 
15
16
  def render(tree)
@@ -108,7 +109,11 @@ module Elasticsearch
108
109
  text = ''
109
110
  text = description.operation if description.operation
110
111
  if description.field && description.value
111
- text += "(#{field(description.field)}:#{value(description.value)})"
112
+ if @show_values
113
+ text += "(#{field(description.field)}:#{value(description.value)})"
114
+ else
115
+ text += "(#{field(description.field)})"
116
+ end
112
117
  elsif description.field
113
118
  text += "(#{field(description.field)})"
114
119
  end
@@ -0,0 +1,21 @@
1
+ module Elasticsearch
2
+ module API
3
+ module Response
4
+ module StringHelper
5
+ WORD = /[\w\.\*]+/
6
+ WITH_QUOTE = /"[^"]*"/
7
+ WITH_BRACKET = /\[[^\]]*\]/
8
+ QUOTE_TOKENIZER = /(?:(?<field>#{WORD})(\:(?<value>(#{WORD}|#{WITH_QUOTE}|#{WITH_BRACKET})))?)+/
9
+
10
+ # @return [Hash] field name as a key and values as a value
11
+ def tokenize_contents(string)
12
+ string
13
+ .scan(QUOTE_TOKENIZER)
14
+ .each_with_object(Hash.new{|h,k| h[k] = []}) { |(field, value), memo|
15
+ memo[field] << value
16
+ }
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -28,77 +28,108 @@ describe Elasticsearch::API::Response::ExplainResponse do
28
28
 
29
29
  describe "#render_in_line" do
30
30
  let(:response) do
31
- described_class.new(fake_response["explanation"], colorize: false, max: 4)
31
+ described_class.new(fake_response["explanation"], colorize: false, max: 5, show_values: show_values)
32
32
  end
33
33
 
34
34
  subject do
35
35
  response.render_in_line
36
36
  end
37
37
 
38
- it "returns summary of explain in line" do
39
- expect(subject).to eq("0.05 = ((0.43(queryWeight) x 0.25(fieldWeight) x 10.0 x 0.99) min 3.4e+38) x 0.5(coord(1/2)) x 1.0(queryBoost)")
38
+ context "with show_values" do
39
+ let(:show_values) do
40
+ true
41
+ end
42
+
43
+ it "returns summary of explain in line" do
44
+ expect(subject).to eq("0.05 = ((1.0(idf(2/3)) x 0.43(queryNorm)) x (1.0(tf(1.0)) x 1.0(idf(2/3)) x 0.25(fieldNorm(doc=0))) x 10.0(match(name.raw:smith)) x 0.99(func(updated_at)) x 5.93(script(popularity:\"def val = factor * log(sqrt(doc['popularity'].value) + 1) + 1\" {factor=1.0})) min 3.4e+38) x 0.5(coord(1/2)) x 1.0(queryBoost)")
45
+ end
46
+
47
+ context "with fake_response2" do
48
+ let(:fake_response) do
49
+ fixture_load(:response2)
50
+ end
51
+
52
+ it "returns summary of explain in line" do
53
+ expect(subject).to eq("887.19 = ((10.0(match(name:hawaii)) x 10.0(match(name:guam)) x 0.7(match(name:\"new caledonia\", new, nueva, caledonia)) x 3.0(match(with_beach:T)) x 0.99(func(updated_at)) x 3.0(match(region_id:[3 TO 3]))) min 3.4e+38) x 1.0(queryBoost)")
54
+ end
55
+ end
40
56
  end
41
57
 
42
- context "with fake_response2" do
43
- let(:fake_response) do
44
- fixture_load(:response2)
58
+ context "with show_values false" do
59
+ let(:show_values) do
60
+ false
45
61
  end
46
62
 
47
63
  it "returns summary of explain in line" do
48
- expect(subject).to eq("887.19 = ((10.0(match(name:hawaii)) x 10.0(match(name:guam)) x 0.7(match(name:\"new caledonia\" (+(name:new name:nueva) +name:caledonia)) x 3.0(match(with_beach:T)) x 0.99(func(updated_at)) x 3.0(match(region_id:[3 TO 3]))) min 3.4e+38) x 1.0(queryBoost)")
64
+ expect(subject).to eq("0.05 = ((1.0(idf(2/3)) x 0.43(queryNorm)) x (1.0(tf(1.0)) x 1.0(idf(2/3)) x 0.25(fieldNorm(doc=0))) x 10.0(match(name.raw)) x 0.99(func(updated_at)) x 5.93(script(popularity)) min 3.4e+38) x 0.5(coord(1/2)) x 1.0(queryBoost)")
65
+ end
66
+
67
+ context "with fake_response2" do
68
+ let(:fake_response) do
69
+ fixture_load(:response2)
70
+ end
71
+
72
+ it "returns summary of explain in line" do
73
+ expect(subject).to eq("887.19 = ((10.0(match(name)) x 10.0(match(name)) x 0.7(match(name)) x 3.0(match(with_beach)) x 0.99(func(updated_at)) x 3.0(match(region_id))) min 3.4e+38) x 1.0(queryBoost)")
74
+ end
49
75
  end
50
76
  end
51
77
  end
52
78
 
53
79
  describe "#render" do
54
80
  let(:response) do
55
- described_class.new(fake_response["explanation"], max: max, colorize: false, plain_score: plain_score)
81
+ described_class.new(fake_response["explanation"], max: max, colorize: false, plain_score: plain_score, show_values: show_values)
56
82
  end
57
83
 
58
84
  let(:max) { nil }
59
85
  let(:plain_score) { nil }
86
+ let(:show_values) { false }
60
87
 
61
88
  subject do
62
89
  response.render.lines.map(&:rstrip)
63
90
  end
64
91
 
65
- it "returns summary of explain in lines" do
66
- expect(subject).to match_array [
67
- "0.05 = 0.11 x 0.5(coord(1/2)) x 1.0(queryBoost)",
68
- " 0.11 = 0.11 min 3.4e+38",
69
- " 0.11 = 0.11(weight(_all:smith))",
70
- " 0.11 = 0.11(score)"
71
- ]
72
- end
73
-
74
- context "with max = 5" do
75
- let(:max) { 5 }
92
+ context "with show_values" do
93
+ let(:show_values) { true }
76
94
 
77
95
  it "returns summary of explain in lines" do
78
- expect(subject).to match_array([
96
+ expect(subject).to match_array [
79
97
  "0.05 = 0.11 x 0.5(coord(1/2)) x 1.0(queryBoost)",
80
98
  " 0.11 = 0.11 min 3.4e+38",
81
99
  " 0.11 = 0.11(weight(_all:smith))",
82
- " 0.11 = 0.11(score)",
83
- " 0.11 = 0.43(queryWeight) x 0.25(fieldWeight) x 10.0 x 0.99",
84
- " 0.43 = 1.0(idf(2/3)) x 0.43(queryNorm)",
85
- " 0.25 = 1.0(tf(1.0)) x 1.0(idf(2/3)) x 0.25(fieldNorm(doc=0))",
86
- " 10.0 = 10.0 x 1.0(match(name.raw:smith))",
87
- " 0.99 = 0.99(func(updated_at))"
88
- ])
100
+ " 0.11 = 0.11(score)"
101
+ ]
89
102
  end
90
- end
91
103
 
92
- context "with plain_score = true" do
93
- let(:plain_score) { true }
104
+ context "with max = 5" do
105
+ let(:max) { 5 }
106
+
107
+ it "returns summary of explain in lines" do
108
+ expect(subject).to match_array([
109
+ "0.05 = 0.11 x 0.5(coord(1/2)) x 1.0(queryBoost)",
110
+ " 0.11 = 0.11 min 3.4e+38",
111
+ " 0.11 = 0.11(weight(_all:smith))",
112
+ " 0.11 = 0.11(score)",
113
+ " 0.11 = 0.43(queryWeight) x 0.25(fieldWeight) x 10.0 x 0.99 x 5.93(script(popularity:\"def val = factor * log(sqrt(doc['popularity'].value) + 1) + 1\" {factor=1.0}))",
114
+ " 0.43 = 1.0(idf(2/3)) x 0.43(queryNorm)",
115
+ " 0.25 = 1.0(tf(1.0)) x 1.0(idf(2/3)) x 0.25(fieldNorm(doc=0))",
116
+ " 10.0 = 10.0 x 1.0(match(name.raw:smith))",
117
+ " 0.99 = 0.99(func(updated_at))"
118
+ ])
119
+ end
120
+ end
94
121
 
95
- it "returns summary of explain in lines" do
96
- expect(subject).to match_array([
97
- "0.05 = 0.11 x 0.5(coord(1/2)) x 1.0(queryBoost)",
98
- " 0.11 = 0.11 min 3.4028235e+38",
99
- " 0.11 = 0.11(weight(_all:smith))",
100
- " 0.11 = 0.11(score)"
101
- ])
122
+ context "with plain_score = true" do
123
+ let(:plain_score) { true }
124
+
125
+ it "returns summary of explain in lines" do
126
+ expect(subject).to match_array([
127
+ "0.05 = 0.11 x 0.5(coord(1/2)) x 1.0(queryBoost)",
128
+ " 0.11 = 0.11 min 3.4028235e+38",
129
+ " 0.11 = 0.11(weight(_all:smith))",
130
+ " 0.11 = 0.11(score)"
131
+ ])
132
+ end
102
133
  end
103
134
  end
104
135
  end
@@ -59,6 +59,10 @@ explanation:
59
59
  - value: 0.9857722
60
60
  description: "exp(- MIN[Math.max(Math.abs(1.424917503E12(=doc value)\
61
61
  \ - 1.432308964176E12(=origin))) - 0.0(=offset), 0)] * 1.938722193962471E-12)"
62
+ - value: 5.9284687
63
+ description: "script score function, computed with script:\"def val\
64
+ \ = factor * log(sqrt(doc['popularity'].value)\
65
+ \ + 1) + 1\" and parameters: \n{factor=1.0}"
62
66
  - value: 3.4028235E+38
63
67
  description: "maxBoost"
64
68
  - value: 0.5
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elasticsearch-explain-response
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.5
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomoya Hirano
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-06-17 00:00:00.000000000 Z
11
+ date: 2015-09-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -115,6 +115,7 @@ files:
115
115
  - lib/elasticsearch/api/response/explain_parser.rb
116
116
  - lib/elasticsearch/api/response/explain_renderer.rb
117
117
  - lib/elasticsearch/api/response/explain_response.rb
118
+ - lib/elasticsearch/api/response/string_helper.rb
118
119
  - spec/elasticsearch/api/response/explain_response_spec.rb
119
120
  - spec/fixtures/response1.yml
120
121
  - spec/fixtures/response2.yml