inquisitio 2.0.0 → 2.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 +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/inquisitio/facets.rb +16 -0
- data/lib/inquisitio/search_url_builder.rb +44 -44
- data/lib/inquisitio/searcher.rb +72 -31
- data/lib/inquisitio/version.rb +1 -1
- data/lib/inquisitio.rb +1 -0
- data/test/facets_test.rb +72 -0
- data/test/results_test.rb +4 -1
- data/test/search_url_builder_test.rb +38 -23
- data/test/searcher_test.rb +56 -14
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f276ddda623e737c046197a26d4696dc87859265
|
4
|
+
data.tar.gz: 60eac7285494fc1adad7edb022ca36e6030f9db5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59bc49ebc2a61c0dcf17118ad7de9329be918b13088df8c78e9175ec8bb964135523e3972a743864b704057442e4e4f39286933ed3b131528682004eb96246fe
|
7
|
+
data.tar.gz: b48f671ce616589f245bd9ecf308920832900ca35711385579b9544324769e3f37e0d7b08436f9a5ade1a63539467b0c569a250d1f1dba783e3d3ae7c079689c
|
data/CHANGELOG.md
CHANGED
@@ -6,78 +6,78 @@ module Inquisitio
|
|
6
6
|
end
|
7
7
|
|
8
8
|
def initialize(options = {})
|
9
|
-
@
|
10
|
-
@
|
9
|
+
@query_terms = options[:query][:terms]
|
10
|
+
@query_named_fields = options[:query][:named_fields] || {}
|
11
|
+
@filter_query = options[:filter_query] || {}
|
12
|
+
@filter_query_terms = @filter_query[:terms] || []
|
13
|
+
@filter_query_named_fields = @filter_query[:named_fields] || {}
|
14
|
+
@facets = options[:facets] || {}
|
11
15
|
@q_options = options[:q_options] || {}
|
12
16
|
@expressions = options[:expressions] || {}
|
13
|
-
@arguments = options[:arguments] || {}
|
14
17
|
@return_fields = options[:return_fields] || []
|
15
18
|
@size = options[:size] || Inquisitio.config.default_search_size
|
16
19
|
@start = options[:start] || 0
|
17
20
|
@sort = options[:sort] || {}
|
18
|
-
@q_parser = options[:q_parser] || (is_simple? ? nil : :structured)
|
21
|
+
@q_parser = options[:q_parser] || (is_simple?(@query_terms, @query_named_fields) ? nil : :structured)
|
19
22
|
end
|
20
23
|
|
21
24
|
def build
|
22
|
-
components = [
|
23
|
-
components <<
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
components <<
|
25
|
+
components = []
|
26
|
+
components << 'q=' + CGI::escape(build_query(@query_terms, @query_named_fields))
|
27
|
+
if !@filter_query_terms.empty? || !@filter_query_named_fields.empty?
|
28
|
+
components << 'fq=' + CGI::escape(build_query(@filter_query_terms, @filter_query_named_fields))
|
29
|
+
end
|
30
|
+
components << "q.parser=#{@q_parser}" if @q_parser
|
31
|
+
components << "return=#{CGI::escape(@return_fields.join(',').gsub('\'', ''))}" unless @return_fields.empty?
|
32
|
+
# components << arguments
|
33
|
+
@facets.each do |field,settings|
|
34
|
+
components << "facet.#{field}=#{CGI::escape(settings.to_json)}"
|
35
|
+
end
|
36
|
+
components << 'q.options=' + CGI::escape(@q_options.to_json) unless @q_options.empty?
|
28
37
|
@expressions.each do |name, expression|
|
29
|
-
components << "
|
38
|
+
components << "expr.#{name}=" + CGI::escape(expression)
|
30
39
|
end
|
31
|
-
components << "
|
32
|
-
components << "
|
33
|
-
components << '
|
34
|
-
components.join('')
|
40
|
+
components << "size=#{@size}"
|
41
|
+
components << "start=#{@start}" unless @start == 0 || @start == '0'
|
42
|
+
components << 'sort=' + @sort.map { |k, v| "#{k}%20#{v}" }.join(',') unless @sort.empty?
|
43
|
+
url_root + components.join('&')
|
35
44
|
end
|
36
45
|
|
37
|
-
def is_simple?
|
38
|
-
|
46
|
+
def is_simple?(terms, named_fields)
|
47
|
+
Array(terms).size == 1 && named_fields.empty?
|
39
48
|
end
|
40
49
|
|
41
50
|
private
|
42
|
-
def simple_query
|
43
|
-
"q=#{CGI::escape(@query.first)}"
|
44
|
-
end
|
45
|
-
|
46
|
-
def boolean_query
|
47
51
|
|
52
|
+
def build_query(terms, named_fields)
|
53
|
+
return terms.first if is_simple?(terms, named_fields)
|
48
54
|
query_blocks = []
|
55
|
+
query_blocks << '(and' unless terms.empty? || named_fields.empty?
|
49
56
|
|
50
|
-
if
|
51
|
-
|
52
|
-
elsif
|
53
|
-
query_blocks << "'#{
|
54
|
-
else
|
55
|
-
query_blocks << "(or #{@query.map { |q| "'#{sanitise(q)}'" }.join(' ')})"
|
57
|
+
if terms.size == 1
|
58
|
+
query_blocks << "'#{dequote(terms.first)}'"
|
59
|
+
elsif terms.size > 1
|
60
|
+
query_blocks << "(or #{terms.map { |q| "'#{dequote(q)}'" }.join(' ')})"
|
56
61
|
end
|
57
62
|
|
58
|
-
query_blocks
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
63
|
+
return query_blocks.join(' ') if named_fields.empty?
|
64
|
+
|
65
|
+
query_blocks += named_fields.map do |key, value|
|
66
|
+
raise InquisitioError.new('Named field values must be strings or arrays.') unless value.is_a?(String) || value.is_a?(Array)
|
67
|
+
block = "#{dequote(key)}:'#{dequote(value)}'" if value.is_a?(String)
|
68
|
+
block = "#{dequote(key)}:'#{dequote(value.first)}'" if value.is_a?(Array) && value.size == 1
|
69
|
+
block = "(or #{value.map { |v| "#{dequote(key)}:'#{dequote(v)}'" }.join(' ')})" if value.is_a?(Array) && value.size > 1
|
70
|
+
block
|
66
71
|
end
|
67
72
|
|
68
|
-
|
73
|
+
query_blocks << ')' unless terms.empty? || named_fields.empty?
|
74
|
+
query_blocks.join(' ')
|
69
75
|
end
|
70
76
|
|
71
|
-
def
|
77
|
+
def dequote(value)
|
72
78
|
value.to_s.gsub('\'', '')
|
73
79
|
end
|
74
80
|
|
75
|
-
|
76
|
-
def arguments
|
77
|
-
return '' if @arguments.nil?
|
78
|
-
@arguments.map { |key, value| "&#{key.to_s.gsub('\'', '')}=#{value.to_s.gsub('\'', '')}" }.join("")
|
79
|
-
end
|
80
|
-
|
81
81
|
def url_root
|
82
82
|
"#{Inquisitio.config.search_endpoint}/#{Inquisitio.config.api_version}/search?"
|
83
83
|
end
|
data/lib/inquisitio/searcher.rb
CHANGED
@@ -11,8 +11,11 @@ module Inquisitio
|
|
11
11
|
|
12
12
|
def initialize(params = nil)
|
13
13
|
@params = params || {
|
14
|
-
|
15
|
-
|
14
|
+
query_terms: [],
|
15
|
+
query_named_fields: {},
|
16
|
+
filter_query_terms: [],
|
17
|
+
filter_query_named_fields: {},
|
18
|
+
facets: {},
|
16
19
|
per: 10,
|
17
20
|
page: 1,
|
18
21
|
returns: [],
|
@@ -20,7 +23,6 @@ module Inquisitio
|
|
20
23
|
q_options: {},
|
21
24
|
expressions: {}
|
22
25
|
}
|
23
|
-
@failed_attempts = 0
|
24
26
|
|
25
27
|
yield(self) if block_given?
|
26
28
|
end
|
@@ -67,19 +69,42 @@ module Inquisitio
|
|
67
69
|
def where(value)
|
68
70
|
clone do |s|
|
69
71
|
if value.is_a?(Array)
|
70
|
-
s.params[:
|
72
|
+
s.params[:query_terms] += value
|
71
73
|
elsif value.is_a?(Hash)
|
72
74
|
value.each do |k, v|
|
73
75
|
k = k.to_sym
|
74
|
-
s.params[:
|
76
|
+
s.params[:query_named_fields][k] ||= []
|
75
77
|
if v.is_a?(Array)
|
76
|
-
s.params[:
|
78
|
+
s.params[:query_named_fields][k] = v
|
77
79
|
else
|
78
|
-
s.params[:
|
80
|
+
s.params[:query_named_fields][k] << v
|
79
81
|
end
|
80
82
|
end
|
81
83
|
else
|
82
|
-
s.params[:
|
84
|
+
s.params[:query_terms] << value
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def filter(value)
|
90
|
+
clone do |s|
|
91
|
+
if value.nil?
|
92
|
+
s.params[:filter_query_terms] = []
|
93
|
+
s.params[:filter_query_named_fields] = {}
|
94
|
+
elsif value.is_a?(Array)
|
95
|
+
s.params[:filter_query_terms] += value
|
96
|
+
elsif value.is_a?(Hash)
|
97
|
+
value.each do |k, v|
|
98
|
+
k = k.to_sym
|
99
|
+
s.params[:filter_query_named_fields][k] ||= []
|
100
|
+
if v.is_a?(Array)
|
101
|
+
s.params[:filter_query_named_fields][k] = v
|
102
|
+
else
|
103
|
+
s.params[:filter_query_named_fields][k] << v
|
104
|
+
end
|
105
|
+
end
|
106
|
+
else
|
107
|
+
s.params[:filter_query_terms] << value
|
83
108
|
end
|
84
109
|
end
|
85
110
|
end
|
@@ -90,6 +115,12 @@ module Inquisitio
|
|
90
115
|
end
|
91
116
|
end
|
92
117
|
|
118
|
+
def facets(value)
|
119
|
+
clone do |s|
|
120
|
+
s.params[:facets] = value
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
93
124
|
def expressions(value)
|
94
125
|
clone do |s|
|
95
126
|
s.params[:expressions] = value
|
@@ -130,6 +161,10 @@ module Inquisitio
|
|
130
161
|
end
|
131
162
|
end
|
132
163
|
|
164
|
+
def result_facets
|
165
|
+
@result_facets ||= Facets.new(cloudsearch_body['facets'])
|
166
|
+
end
|
167
|
+
|
133
168
|
# Proxy everything to the results so that this this class
|
134
169
|
# transparently acts as an Array.
|
135
170
|
def method_missing(name, *args, &block)
|
@@ -139,35 +174,41 @@ module Inquisitio
|
|
139
174
|
private
|
140
175
|
|
141
176
|
def results
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
177
|
+
@results ||= begin
|
178
|
+
Results.new(cloudsearch_body['hits']['hit'],
|
179
|
+
params[:page],
|
180
|
+
params[:per],
|
181
|
+
cloudsearch_body['hits']['found'],
|
182
|
+
cloudsearch_body['status']['time-ms'])
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
def cloudsearch_body
|
187
|
+
failed = 0
|
188
|
+
@cloudsearch_body ||= begin
|
189
|
+
Inquisitio.config.logger.info("Performing search: #{search_url}")
|
190
|
+
response = Excon.get(search_url)
|
191
|
+
raise InquisitioError.new("Search failed with status code: #{response.status} Message #{response.body}") unless response.status == 200
|
192
|
+
JSON.parse(response.body)
|
193
|
+
rescue => e
|
194
|
+
failed += 1
|
195
|
+
Inquisitio.config.logger.error("Exception Performing search: #{search_url} #{e}")
|
196
|
+
|
197
|
+
if failed < Inquisitio.config.max_attempts
|
198
|
+
Inquisitio.config.logger.error("Retrying search #{@failed_attempts}/#{Inquisitio.config.max_attempts}")
|
199
|
+
retry
|
200
|
+
else
|
201
|
+
raise InquisitioError.new('Exception performing search')
|
202
|
+
end
|
163
203
|
end
|
164
204
|
end
|
165
205
|
|
166
206
|
def search_url
|
167
207
|
@search_url ||= begin
|
168
208
|
SearchUrlBuilder.build(
|
169
|
-
query: params[:
|
170
|
-
named_fields: params[:
|
209
|
+
query: {terms: params[:query_terms], named_fields: params[:query_named_fields]},
|
210
|
+
filter_query: {terms: params[:filter_query_terms], named_fields: params[:filter_query_named_fields]},
|
211
|
+
facets: params[:facets],
|
171
212
|
size: params[:per],
|
172
213
|
start: params[:per] * (params[:page] - 1),
|
173
214
|
sort: params[:sort],
|
data/lib/inquisitio/version.rb
CHANGED
data/lib/inquisitio.rb
CHANGED
data/test/facets_test.rb
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
require File.expand_path('../test_helper', __FILE__)
|
2
|
+
|
3
|
+
module Inquisitio
|
4
|
+
class FacetsTest < Minitest::Test
|
5
|
+
def setup
|
6
|
+
super
|
7
|
+
@search_endpoint = 'http://my.search-endpoint.com'
|
8
|
+
Inquisitio.config.search_endpoint = @search_endpoint
|
9
|
+
@body = {
|
10
|
+
'status' => {'rid' => '9d3b24b', 'time-ms' => 3},
|
11
|
+
'hits' => {'found' => 1, 'start' => 0, 'hit' => [{'data' => {'id' => ['20'], 'title' => ['Foobar2'], 'type' => ['Module_Dog']}}], },
|
12
|
+
'facets' => {
|
13
|
+
'genres' => {
|
14
|
+
'buckets' => [
|
15
|
+
{'value' => 'Drama', 'count' => 12},
|
16
|
+
{'value' => 'Romance', 'count' => 9}]
|
17
|
+
},
|
18
|
+
'rating' => {
|
19
|
+
'buckets' => [
|
20
|
+
{'value' => '6.3', 'count' => 3},
|
21
|
+
{'value' => '6.2', 'count' => 2},
|
22
|
+
{'value' => '7.1', 'count' => 2},
|
23
|
+
{'value' => '7.6', 'count' => 1}]
|
24
|
+
},
|
25
|
+
}
|
26
|
+
}.to_json
|
27
|
+
|
28
|
+
Excon.defaults[:mock] = true
|
29
|
+
Excon.stub({}, {body: @body, status: 200})
|
30
|
+
end
|
31
|
+
|
32
|
+
def teardown
|
33
|
+
super
|
34
|
+
Excon.stubs.clear
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_should_return_fields
|
38
|
+
searcher = Searcher.where('star_wars')
|
39
|
+
facets = searcher.result_facets
|
40
|
+
assert_equal [:genres, :rating], facets.fields
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_should_access_buckets_by_symbols
|
44
|
+
searcher = Searcher.where('star_wars')
|
45
|
+
facets = searcher.result_facets
|
46
|
+
refute_nil facets[:genres]
|
47
|
+
refute_nil facets[:rating]
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_should_have_bucket_lengths
|
51
|
+
searcher = Searcher.where('star_wars')
|
52
|
+
facets = searcher.result_facets
|
53
|
+
assert_equal 2, facets[:genres][:buckets].length
|
54
|
+
assert_equal 4, facets[:rating][:buckets].length
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_should_have_bucket_entry_values
|
58
|
+
searcher = Searcher.where('star_wars')
|
59
|
+
facets = searcher.result_facets
|
60
|
+
assert_equal 'Drama', facets[:genres][:buckets].first[:value]
|
61
|
+
assert_equal '6.2', facets[:rating][:buckets][1][:value]
|
62
|
+
end
|
63
|
+
|
64
|
+
def test_should_have_bucket_entry_counts
|
65
|
+
searcher = Searcher.where('star_wars')
|
66
|
+
facets = searcher.result_facets
|
67
|
+
assert_equal 12, facets[:genres][:buckets].first[:count]
|
68
|
+
assert_equal 2, facets[:rating][:buckets][1][:count]
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
72
|
+
end
|
data/test/results_test.rb
CHANGED
@@ -41,7 +41,10 @@ module Inquisitio
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def test_should_return_time_taken
|
44
|
-
body =
|
44
|
+
body = {
|
45
|
+
'status' => {'rid' => 'u9aP4eYo8gIK0csK', 'time-ms' => 4},
|
46
|
+
'hits' => {'found' => 33, 'start' => 0, 'hit' => @expected_results}
|
47
|
+
}.to_json
|
45
48
|
Excon.stubs.clear
|
46
49
|
Excon.stub({}, {body: body, status: 200})
|
47
50
|
|
@@ -10,94 +10,109 @@ module Inquisitio
|
|
10
10
|
Inquisitio.config.default_search_size = '10'
|
11
11
|
end
|
12
12
|
|
13
|
+
def test_uses_endpoint
|
14
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars']})
|
15
|
+
assert (/^#{@search_endpoint}\/2013-01-01\/search(\?|$)/ =~ url), "Should start with endpoint: #{url}"
|
16
|
+
end
|
17
|
+
|
13
18
|
def test_create_correct_search_url_with_single_criteria_query
|
14
|
-
url = SearchUrlBuilder.build(query: ['Star Wars'])
|
15
|
-
|
16
|
-
|
19
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars']})
|
20
|
+
assert /(&|\?)q=Star\+Wars(&|$)/ =~ url
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_create_correct_search_url_with_single_criteria_query_and_single_filter_criteria
|
24
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars']}, filter_query: {terms: ['A New Hope']})
|
25
|
+
assert /(&|\?)q=Star\+Wars(&|$)/ =~ url, "should have query in url: #{url}"
|
26
|
+
assert /(&|\?)fq=A\+New\+Hope(&|$)/ =~ url, "should have filter query in url: #{url}"
|
17
27
|
end
|
18
28
|
|
19
29
|
def test_create_correct_search_url_with_ampersand
|
20
|
-
url = SearchUrlBuilder.build(query: ['Star&Wars'])
|
30
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star&Wars']})
|
21
31
|
expected_url = 'http://my.search-endpoint.com/2013-01-01/search?q=Star%26Wars&size=10'
|
22
32
|
assert_equal expected_url, url
|
23
33
|
end
|
24
34
|
|
25
35
|
def test_create_correct_search_url_with_multiple_criteria_should_use_structured_parser
|
26
|
-
url = SearchUrlBuilder.build(query: ['Star Wars', 'Episode One'])
|
27
|
-
expected_url = 'http://my.search-endpoint.com/2013-01-01/search?q=%
|
36
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars', 'Episode One']})
|
37
|
+
expected_url = 'http://my.search-endpoint.com/2013-01-01/search?q=%28or+%27Star+Wars%27+%27Episode+One%27%29&q.parser=structured&size=10'
|
28
38
|
assert_equal expected_url, url
|
29
39
|
end
|
30
40
|
|
31
41
|
def test_create_correct_search_url_with_multiple_criteria_with_ampersand
|
32
|
-
url = SearchUrlBuilder.build(query: ['Star&Wars', 'Episode One'])
|
33
|
-
expected_url = 'http://my.search-endpoint.com/2013-01-01/search?q=%
|
42
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star&Wars', 'Episode One']})
|
43
|
+
expected_url = 'http://my.search-endpoint.com/2013-01-01/search?q=%28or+%27Star%26Wars%27+%27Episode+One%27%29&q.parser=structured&size=10'
|
34
44
|
assert_equal expected_url, url
|
35
45
|
end
|
36
46
|
|
37
47
|
def test_create_correct_search_url_including_return_fields
|
38
|
-
url = SearchUrlBuilder.build(query: ['Star Wars'], return_fields: %w(title year %))
|
48
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars']}, return_fields: %w(title year %))
|
39
49
|
expected_url = 'http://my.search-endpoint.com/2013-01-01/search?q=Star+Wars&return=title%2Cyear%2C%25&size=10'
|
40
50
|
assert_equal expected_url, url
|
41
51
|
end
|
42
52
|
|
43
53
|
def test_create_search_url_with_default_size
|
44
|
-
url = SearchUrlBuilder.build(query: ['Star Wars'])
|
54
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars']})
|
45
55
|
expected_url = 'http://my.search-endpoint.com/2013-01-01/search?q=Star+Wars&size=10'
|
46
56
|
assert_equal expected_url, url
|
47
57
|
end
|
48
58
|
|
49
59
|
def test_create_search_url_overriding_default_size
|
50
|
-
url = SearchUrlBuilder.build(query: ['Star Wars'], size: '200')
|
60
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars']}, size: '200')
|
51
61
|
expected_url = 'http://my.search-endpoint.com/2013-01-01/search?q=Star+Wars&size=200'
|
52
62
|
assert_equal expected_url, url
|
53
63
|
end
|
54
64
|
|
55
65
|
def test_create_search_url_with_start_and_default_size
|
56
|
-
url = SearchUrlBuilder.build(query: ['Star Wars'], start: '20')
|
66
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars']}, start: '20')
|
57
67
|
assert /(&|\?)start=20(&|$)/ =~ url
|
58
68
|
assert /(&|\?)size=10(&|$)/ =~ url
|
59
69
|
end
|
60
70
|
|
61
71
|
def test_create_search_url_with_start_and_size
|
62
|
-
url = SearchUrlBuilder.build(query: ['Star Wars'], start: '2', size: '200')
|
72
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars']}, start: '2', size: '200')
|
63
73
|
assert /(&|\?)start=2(&|$)/ =~ url
|
64
74
|
assert /(&|\?)size=200(&|$)/ =~ url
|
65
75
|
end
|
66
76
|
|
67
77
|
def test_create_search_url_with_named_fields_array
|
68
|
-
url = SearchUrlBuilder.build(query: ['Star Wars'], named_fields: {genre:
|
69
|
-
|
70
|
-
|
71
|
-
|
78
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars'], named_fields: {genre: %w(Animation Action)}})
|
79
|
+
assert /(&|\?)q=%28and\+%27Star\+Wars%27\+%28or\+genre%3A%27Animation%27\+genre%3A%27Action%27%29\+%29(&|$)/ =~ url
|
80
|
+
assert /(&|\?)q.parser=structured(&|$)/ =~ url
|
81
|
+
end
|
82
|
+
|
83
|
+
def test_create_search_url_with_named_fields_in_filter_query
|
84
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars']}, filter_query: {terms: ['A New Hope'], named_fields: {genre: %w(Animation Action)}})
|
85
|
+
assert /(&|\?)q=Star\+Wars(&|$)/ =~ url, "should have query in url: #{url}"
|
86
|
+
assert /(&|\?)fq=%28and\+%27A\+New\+Hope%27\+%28or\+genre%3A%27Animation%27\+genre%3A%27Action%27%29\+%29(&|$)/ =~ url, "should have filter query in url: #{url}"
|
72
87
|
end
|
73
88
|
|
74
89
|
def test_create_search_url_with_query_options
|
75
|
-
url = SearchUrlBuilder.build(query: ['Star Wars'], q_options: {fields: %w(title^2.0 plot^0.5)})
|
90
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars']}, q_options: {fields: %w(title^2.0 plot^0.5)})
|
76
91
|
expected_url = 'http://my.search-endpoint.com/2013-01-01/search?q=Star+Wars&q.options=%7B%22fields%22%3A%5B%22title%5E2.0%22%2C%22plot%5E0.5%22%5D%7D&size=10'
|
77
92
|
assert_equal expected_url, url
|
78
93
|
end
|
79
94
|
|
80
95
|
def test_create_search_url_with_query_defaultoperator_option
|
81
|
-
url = SearchUrlBuilder.build(query: ['Star Wars'], q_options: {defaultOperator: 'or'})
|
96
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars']}, q_options: {defaultOperator: 'or'})
|
82
97
|
expected_url = 'http://my.search-endpoint.com/2013-01-01/search?q=Star+Wars&q.options=%7B%22defaultOperator%22%3A%22or%22%7D&size=10'
|
83
98
|
assert_equal expected_url, url
|
84
99
|
end
|
85
100
|
|
86
101
|
def test_create_search_url_with_expressions
|
87
|
-
url = SearchUrlBuilder.build(query: ['Star Wars'], expressions: {rank1: 'log10(clicks)*_score', rank2: 'cos( _score)'})
|
102
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars']}, expressions: {rank1: 'log10(clicks)*_score', rank2: 'cos( _score)'})
|
88
103
|
expected_url = 'http://my.search-endpoint.com/2013-01-01/search?q=Star+Wars&expr.rank1=log10%28clicks%29%2A_score&expr.rank2=cos%28+_score%29&size=10'
|
89
104
|
assert_equal expected_url, url
|
90
105
|
end
|
91
106
|
|
92
107
|
def test_create_url_with_parser
|
93
|
-
url = SearchUrlBuilder.build(query: ['Star Wars'], q_parser: :structured)
|
108
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars']}, q_parser: :structured)
|
94
109
|
expected_url = 'http://my.search-endpoint.com/2013-01-01/search?q=Star+Wars&q.parser=structured&size=10'
|
95
110
|
assert_equal expected_url, url
|
96
111
|
end
|
97
112
|
|
98
113
|
def test_create_url_with_overridden_parser
|
99
|
-
url = SearchUrlBuilder.build(query: ['Star Wars', 'Star Trek'], q_parser: :simple)
|
100
|
-
expected_url = 'http://my.search-endpoint.com/2013-01-01/search?q=%
|
114
|
+
url = SearchUrlBuilder.build(query: {terms: ['Star Wars', 'Star Trek']}, q_parser: :simple)
|
115
|
+
expected_url = 'http://my.search-endpoint.com/2013-01-01/search?q=%28or+%27Star+Wars%27+%27Star+Trek%27%29&q.parser=simple&size=10'
|
101
116
|
assert_equal expected_url, url
|
102
117
|
end
|
103
118
|
|
data/test/searcher_test.rb
CHANGED
@@ -55,20 +55,20 @@ module Inquisitio
|
|
55
55
|
def test_where_sets_variable
|
56
56
|
criteria = 'Star Wars'
|
57
57
|
searcher = Searcher.where(criteria)
|
58
|
-
assert_equal [criteria], searcher.params[:
|
58
|
+
assert_equal [criteria], searcher.params[:query_terms]
|
59
59
|
end
|
60
60
|
|
61
61
|
def test_where_sets_variable_with_an_array
|
62
62
|
criteria = %w(Star Wars)
|
63
63
|
searcher = Searcher.where(criteria)
|
64
|
-
assert_equal criteria, searcher.params[:
|
64
|
+
assert_equal criteria, searcher.params[:query_terms]
|
65
65
|
end
|
66
66
|
|
67
67
|
def test_where_doesnt_mutate_searcher
|
68
68
|
initial_criteria = 'star wars'
|
69
69
|
searcher = Searcher.where(initial_criteria)
|
70
70
|
searcher.where('Return of the Jedi')
|
71
|
-
assert_equal [initial_criteria], searcher.params[:
|
71
|
+
assert_equal [initial_criteria], searcher.params[:query_terms]
|
72
72
|
end
|
73
73
|
|
74
74
|
def test_where_returns_a_new_searcher
|
@@ -80,28 +80,28 @@ module Inquisitio
|
|
80
80
|
def test_where_sets_named_fields
|
81
81
|
named_fields = {genre: 'Animation'}
|
82
82
|
searcher = Searcher.where(named_fields)
|
83
|
-
assert_equal({genre: ['Animation']}, searcher.params[:
|
83
|
+
assert_equal({genre: ['Animation']}, searcher.params[:query_named_fields])
|
84
84
|
end
|
85
85
|
|
86
86
|
def test_where_merges_named_fields
|
87
87
|
named_fields1 = {genre: 'Animation'}
|
88
88
|
named_fields2 = {foobar: 'Cat'}
|
89
89
|
searcher = Searcher.where(named_fields1).where(named_fields2)
|
90
|
-
assert_equal({genre: ['Animation'], foobar: ['Cat']}, searcher.params[:
|
90
|
+
assert_equal({genre: ['Animation'], foobar: ['Cat']}, searcher.params[:query_named_fields])
|
91
91
|
end
|
92
92
|
|
93
93
|
def test_symbolizes_where_keys
|
94
94
|
named_fields1 = {'genre' => 'Animation'}
|
95
95
|
named_fields2 = {'foobar' => 'Cat'}
|
96
96
|
searcher = Searcher.where(named_fields1).where(named_fields2)
|
97
|
-
assert_equal({genre: ['Animation'], foobar: ['Cat']}, searcher.params[:
|
97
|
+
assert_equal({genre: ['Animation'], foobar: ['Cat']}, searcher.params[:query_named_fields])
|
98
98
|
end
|
99
99
|
|
100
100
|
def test_where_merges_named_fields_with_same_key
|
101
101
|
named_fields1 = {genre: 'Animation'}
|
102
102
|
named_fields2 = {genre: 'Action'}
|
103
103
|
searcher = Searcher.where(named_fields1).where(named_fields2)
|
104
|
-
assert_equal({genre: %w(Animation Action)}, searcher.params[:
|
104
|
+
assert_equal({genre: %w(Animation Action)}, searcher.params[:query_named_fields])
|
105
105
|
end
|
106
106
|
|
107
107
|
def test_where_gets_correct_url
|
@@ -113,21 +113,22 @@ module Inquisitio
|
|
113
113
|
def test_where_gets_correct_url_with_fields_in_search
|
114
114
|
searcher = Searcher.where(title: 'Star Wars')
|
115
115
|
search_url = searcher.send(:search_url)
|
116
|
-
assert(
|
116
|
+
assert /(\?|&)q=title%3A%27Star\+Wars%27(&|$)/ =~ search_url, "Search url should include query: #{search_url}"
|
117
|
+
assert /(\?|&)q.parser=structured(&|$)/ =~ search_url, "Search url should include parser: #{search_url}"
|
117
118
|
end
|
118
119
|
|
119
120
|
def test_where_works_with_array_in_a_hash
|
120
121
|
criteria = {thing: %w(foo bar)}
|
121
122
|
searcher = Searcher.where(criteria)
|
122
|
-
assert_equal criteria, searcher.params[:
|
123
|
+
assert_equal criteria, searcher.params[:query_named_fields]
|
123
124
|
end
|
124
125
|
|
125
126
|
def test_where_works_with_string_and_array
|
126
127
|
str_criteria = 'Star Wars'
|
127
128
|
hash_criteria = {thing: %w(foo bar)}
|
128
129
|
searcher = Searcher.where(str_criteria).where(hash_criteria)
|
129
|
-
assert_equal hash_criteria, searcher.params[:
|
130
|
-
assert_equal [str_criteria], searcher.params[:
|
130
|
+
assert_equal hash_criteria, searcher.params[:query_named_fields]
|
131
|
+
assert_equal [str_criteria], searcher.params[:query_terms]
|
131
132
|
end
|
132
133
|
|
133
134
|
def test_per_doesnt_mutate_searcher
|
@@ -303,7 +304,6 @@ module Inquisitio
|
|
303
304
|
end
|
304
305
|
|
305
306
|
def test_should_not_specify_return_by_default
|
306
|
-
Inquisitio.config.api_version = '2013-01-01'
|
307
307
|
searcher = Searcher.where('Star Wars')
|
308
308
|
assert_equal [], searcher.params[:returns]
|
309
309
|
refute searcher.send(:search_url).include? '&return='
|
@@ -405,17 +405,59 @@ module Inquisitio
|
|
405
405
|
end
|
406
406
|
|
407
407
|
def test_should_support_structured_parser
|
408
|
-
Inquisitio.config.api_version = '2013-01-01'
|
409
408
|
searcher = Searcher.where('star wars').parser(:structured)
|
410
409
|
search_url = searcher.send(:search_url)
|
411
410
|
assert search_url =~ /(\?|&)q\.parser=structured(&|$)/, "search url should include q.parser parameter:\n#{search_url}"
|
412
411
|
end
|
413
412
|
|
414
413
|
def test_should_support_any_parser
|
415
|
-
Inquisitio.config.api_version = '2013-01-01'
|
416
414
|
searcher = Searcher.where('star wars').parser(:foo_bar_baz)
|
417
415
|
search_url = searcher.send(:search_url)
|
418
416
|
assert search_url =~ /(\?|&)q\.parser=foo_bar_baz(&|$)/, "search url should include q.parser parameter:\n#{search_url}"
|
419
417
|
end
|
418
|
+
|
419
|
+
def test_should_not_have_fq_if_no_filter
|
420
|
+
searcher = Searcher.where('star wars')
|
421
|
+
search_url = searcher.send(:search_url)
|
422
|
+
refute search_url =~ /(\?|&)fq=/, "search url should not include fq parameter:\n#{search_url}"
|
423
|
+
end
|
424
|
+
|
425
|
+
def test_should_take_a_filter_query
|
426
|
+
searcher = Searcher.where('star wars').filter('a new hope')
|
427
|
+
search_url = searcher.send(:search_url)
|
428
|
+
assert search_url =~ /(\?|&)fq=a\+new\+hope(&|$)/, "search url should include fq parameter:\n#{search_url}"
|
429
|
+
end
|
430
|
+
|
431
|
+
def test_should_take_a_filter_query_with_fields
|
432
|
+
searcher = Searcher.where('star wars').filter(tags: 'anewhope')
|
433
|
+
search_url = searcher.send(:search_url)
|
434
|
+
assert search_url =~ /(\?|&)fq=tags%3A%27anewhope%27(&|$)/, "search url should include fq parameter:\n#{search_url}"
|
435
|
+
end
|
436
|
+
|
437
|
+
def test_should_accept_empty_filter_to_reset_filters
|
438
|
+
searcher = Searcher.where('star wars').filter(tags: 'anewhope').filter(nil)
|
439
|
+
search_url = searcher.send(:search_url)
|
440
|
+
refute search_url =~ /(\?|&)fq=tags%3A%27anewhope%27(&|$)/, "search url should not include fq parameter:\n#{search_url}"
|
441
|
+
end
|
442
|
+
|
443
|
+
def test_should_tolerate_empty_filter
|
444
|
+
searcher = Searcher.where('star wars').filter(nil)
|
445
|
+
search_url = searcher.send(:search_url)
|
446
|
+
refute search_url =~ /(\?|&)fq=/, "search url should not include fq parameter:\n#{search_url}"
|
447
|
+
end
|
448
|
+
|
449
|
+
def test_should_take_a_facet
|
450
|
+
searcher = Searcher.where('star wars').facets(tags: {})
|
451
|
+
search_url = searcher.send(:search_url)
|
452
|
+
assert search_url =~ /(\?|&)facet\.tags=%7B%7D(&|$)/, "search url should include facet.tags parameter:\n#{search_url}"
|
453
|
+
end
|
454
|
+
|
455
|
+
def test_should_take_facets
|
456
|
+
searcher = Searcher.where('star wars').facets(tags: {}, genre: {sort:'bucket', size:5})
|
457
|
+
search_url = searcher.send(:search_url)
|
458
|
+
assert search_url =~ /(\?|&)facet\.tags=%7B%7D(&|$)/, "search url should include facet.tags parameter:\n#{search_url}"
|
459
|
+
assert search_url =~ /(\?|&)facet\.genre=%7B%22sort%22%3A%22bucket%22%2C%22size%22%3A5%7D(&|$)/, "search url should include facet.genre parameter:\n#{search_url}"
|
460
|
+
end
|
461
|
+
|
420
462
|
end
|
421
463
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: inquisitio
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeremy Walker
|
@@ -11,7 +11,7 @@ authors:
|
|
11
11
|
autorequire:
|
12
12
|
bindir: bin
|
13
13
|
cert_chain: []
|
14
|
-
date: 2015-07-
|
14
|
+
date: 2015-07-23 00:00:00.000000000 Z
|
15
15
|
dependencies:
|
16
16
|
- !ruby/object:Gem::Dependency
|
17
17
|
name: excon
|
@@ -120,6 +120,7 @@ files:
|
|
120
120
|
- lib/inquisitio/active_support.rb
|
121
121
|
- lib/inquisitio/configuration.rb
|
122
122
|
- lib/inquisitio/document.rb
|
123
|
+
- lib/inquisitio/facets.rb
|
123
124
|
- lib/inquisitio/indexer.rb
|
124
125
|
- lib/inquisitio/inquisitio_error.rb
|
125
126
|
- lib/inquisitio/logger.rb
|
@@ -129,6 +130,7 @@ files:
|
|
129
130
|
- lib/inquisitio/version.rb
|
130
131
|
- test/configuration_test.rb
|
131
132
|
- test/document_test.rb
|
133
|
+
- test/facets_test.rb
|
132
134
|
- test/indexer_test.rb
|
133
135
|
- test/logger_test.rb
|
134
136
|
- test/results_test.rb
|
@@ -162,6 +164,7 @@ summary: This wraps AWS CloudSearch in a Ruby Gem
|
|
162
164
|
test_files:
|
163
165
|
- test/configuration_test.rb
|
164
166
|
- test/document_test.rb
|
167
|
+
- test/facets_test.rb
|
165
168
|
- test/indexer_test.rb
|
166
169
|
- test/logger_test.rb
|
167
170
|
- test/results_test.rb
|