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