elasticsearch-explain-response 0.0.5 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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