elastic-app-search 7.4.0 → 7.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +287 -20
- data/lib/elastic/app-search/client.rb +16 -2
- data/lib/elastic/app-search/client/analytics.rb +25 -0
- data/lib/elastic/app-search/client/click.rb +15 -0
- data/lib/elastic/app-search/client/credentials.rb +35 -0
- data/lib/elastic/app-search/client/curations.rb +35 -0
- data/lib/elastic/app-search/client/engines.rb +2 -0
- data/lib/elastic/app-search/client/logs.rb +15 -0
- data/lib/elastic/app-search/client/schema.rb +20 -0
- data/lib/elastic/app-search/client/synonyms.rb +35 -0
- data/lib/elastic/app-search/version.rb +1 -1
- data/spec/analytics_spec.rb +82 -0
- data/spec/click_spec.rb +30 -0
- data/spec/client_spec.rb +8 -452
- data/spec/config_helper.rb +4 -0
- data/spec/credentials_spec.rb +75 -0
- data/spec/curations_spec.rb +82 -0
- data/spec/documents_spec.rb +159 -0
- data/spec/engines_spec.rb +74 -0
- data/spec/logs_spec.rb +33 -0
- data/spec/query_suggestion_spec.rb +37 -0
- data/spec/schema_spec.rb +23 -0
- data/spec/search_settings_spec.rb +65 -0
- data/spec/search_spec.rb +96 -0
- data/spec/spec_helper.rb +69 -0
- data/spec/synonyms_spec.rb +65 -0
- metadata +33 -2
@@ -0,0 +1,35 @@
|
|
1
|
+
# Credentials API - https://swiftype.com/documentation/app-search/api/credentials
|
2
|
+
module Elastic
|
3
|
+
module AppSearch
|
4
|
+
class Client
|
5
|
+
module Credentials
|
6
|
+
|
7
|
+
# Retrieve available credentials
|
8
|
+
def list_credentials(current: 1, size: 20)
|
9
|
+
get("credentials", :page => { :current => current, :size => size })
|
10
|
+
end
|
11
|
+
|
12
|
+
# Retrieve a credential
|
13
|
+
def get_credential(name)
|
14
|
+
get("credentials/#{name}")
|
15
|
+
end
|
16
|
+
|
17
|
+
# Create a new credential
|
18
|
+
def create_credential(options)
|
19
|
+
post("credentials", options)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Update an existing credential
|
23
|
+
def update_credential(name, options)
|
24
|
+
put("credentials/#{name}", options)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Destroy an existing credential
|
28
|
+
def destroy_credential(name)
|
29
|
+
delete("credentials/#{name}")
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Curations API - https://swiftype.com/documentation/app-search/api/curations
|
2
|
+
module Elastic
|
3
|
+
module AppSearch
|
4
|
+
class Client
|
5
|
+
module Curations
|
6
|
+
|
7
|
+
# Retrieve available curations for the engine.
|
8
|
+
def list_curations(engine_name, current: 1, size: 20)
|
9
|
+
get("engines/#{engine_name}/curations", :page => { :current => current, :size => size })
|
10
|
+
end
|
11
|
+
|
12
|
+
# Create a new curation.
|
13
|
+
def create_curation(engine_name, options)
|
14
|
+
post("engines/#{engine_name}/curations", options)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Retrieve a curation by id.
|
18
|
+
def get_curation(engine_name, id)
|
19
|
+
get("engines/#{engine_name}/curations/#{id}")
|
20
|
+
end
|
21
|
+
|
22
|
+
# Update an existing curation.
|
23
|
+
def update_curation(engine_name, id, options)
|
24
|
+
put("engines/#{engine_name}/curations/#{id}", options)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Delete a curation by id.
|
28
|
+
def destroy_curation(engine_name, id)
|
29
|
+
delete("engines/#{engine_name}/curations/#{id}")
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -4,6 +4,7 @@ module Elastic
|
|
4
4
|
module AppSearch
|
5
5
|
class Client
|
6
6
|
module Engines
|
7
|
+
|
7
8
|
def list_engines(current: 1, size: 20)
|
8
9
|
get("engines", :page => { :current => current, :size => size })
|
9
10
|
end
|
@@ -21,6 +22,7 @@ module Elastic
|
|
21
22
|
def destroy_engine(engine_name)
|
22
23
|
delete("engines/#{engine_name}")
|
23
24
|
end
|
25
|
+
|
24
26
|
end
|
25
27
|
end
|
26
28
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# Logs API - https://swiftype.com/documentation/app-search/api/logs
|
2
|
+
module Elastic
|
3
|
+
module AppSearch
|
4
|
+
class Client
|
5
|
+
module Logs
|
6
|
+
|
7
|
+
# The API Log displays API request and response data at the Engine level.
|
8
|
+
def get_api_logs(engine_name, options)
|
9
|
+
post("engines/#{engine_name}/logs/api", options)
|
10
|
+
end
|
11
|
+
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Schema API - https://swiftype.com/documentation/app-search/api/schema
|
2
|
+
module Elastic
|
3
|
+
module AppSearch
|
4
|
+
class Client
|
5
|
+
module Schema
|
6
|
+
|
7
|
+
# Retrieve schema for the current engine.
|
8
|
+
def get_schema(engine_name)
|
9
|
+
get("engines/#{engine_name}/schema")
|
10
|
+
end
|
11
|
+
|
12
|
+
# Create a new schema field or update existing schema for the current engine.
|
13
|
+
def update_schema(engine_name, schema)
|
14
|
+
post("engines/#{engine_name}/schema", schema)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Synonyms API - https://swiftype.com/documentation/app-search/api/synonyms
|
2
|
+
module Elastic
|
3
|
+
module AppSearch
|
4
|
+
class Client
|
5
|
+
module Synonyms
|
6
|
+
|
7
|
+
# Retrieve available synonym sets for the engine.
|
8
|
+
def list_synonym_sets(engine_name, current: 1, size: 20)
|
9
|
+
get("engines/#{engine_name}/synonyms", :page => { :current => current, :size => size })
|
10
|
+
end
|
11
|
+
|
12
|
+
# Retrieve a synonym set by id
|
13
|
+
def get_synonym_set(engine_name, id)
|
14
|
+
get("engines/#{engine_name}/synonyms/#{id}")
|
15
|
+
end
|
16
|
+
|
17
|
+
# Create a new synonym set
|
18
|
+
def create_synonym_set(engine_name, body)
|
19
|
+
post("engines/#{engine_name}/synonyms", body)
|
20
|
+
end
|
21
|
+
|
22
|
+
# Update an existing synonym set
|
23
|
+
def update_synonym_set(engine_name, id, body)
|
24
|
+
put("engines/#{engine_name}/synonyms/#{id}", body)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Delete a synonym set by id
|
28
|
+
def destroy_synonym_set(engine_name, id)
|
29
|
+
delete("engines/#{engine_name}/synonyms/#{id}")
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
describe Elastic::AppSearch::Client::Analytics do
|
2
|
+
include_context 'App Search Credentials'
|
3
|
+
include_context 'Test Engine'
|
4
|
+
|
5
|
+
let(:client) { Elastic::AppSearch::Client.new(client_options) }
|
6
|
+
|
7
|
+
context '#get_top_clicks_analytics' do
|
8
|
+
subject do
|
9
|
+
client.get_top_clicks_analytics(
|
10
|
+
engine_name,
|
11
|
+
:query => 'cats',
|
12
|
+
:page => {
|
13
|
+
:size => 20,
|
14
|
+
},
|
15
|
+
:filters => {
|
16
|
+
:date => {
|
17
|
+
:from => Time.now.iso8601,
|
18
|
+
:to => Time.now.iso8601
|
19
|
+
}
|
20
|
+
}
|
21
|
+
)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'will query for analytics' do
|
25
|
+
expect(subject['results']).to(eq([]))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context '#get_top_queries_analytics' do
|
30
|
+
subject do
|
31
|
+
client.get_top_queries_analytics(
|
32
|
+
engine_name,
|
33
|
+
:page => {
|
34
|
+
:size => 20
|
35
|
+
},
|
36
|
+
:filters => {
|
37
|
+
:date => {
|
38
|
+
:from => Time.now.iso8601,
|
39
|
+
:to => Time.now.iso8601
|
40
|
+
}
|
41
|
+
}
|
42
|
+
)
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'will query for analytics' do
|
46
|
+
expect(subject['results']).to(eq([]))
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context '#get_count_analytics' do
|
51
|
+
let(:from) { Time.now.iso8601 }
|
52
|
+
let(:to) { Time.now.iso8601 }
|
53
|
+
|
54
|
+
subject do
|
55
|
+
client.get_count_analytics(
|
56
|
+
engine_name,
|
57
|
+
:filters => {
|
58
|
+
:all => [
|
59
|
+
{
|
60
|
+
:tag => ['mobile', 'web']
|
61
|
+
}, {
|
62
|
+
:query => 'cats'
|
63
|
+
}, {
|
64
|
+
:document_id => '163'
|
65
|
+
}, {
|
66
|
+
:date => {
|
67
|
+
:from => from,
|
68
|
+
:to => to
|
69
|
+
}
|
70
|
+
}
|
71
|
+
]
|
72
|
+
},
|
73
|
+
:interval => 'hour'
|
74
|
+
)
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'will query for analytics' do
|
78
|
+
expect(subject['results'][0]['clicks']).to(eq(0))
|
79
|
+
expect(subject['results'][0]['queries']).to(eq(0))
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
data/spec/click_spec.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
describe Elastic::AppSearch::Client::Click do
|
2
|
+
include_context 'App Search Credentials'
|
3
|
+
include_context 'Test Engine'
|
4
|
+
|
5
|
+
let(:client) { Elastic::AppSearch::Client.new(client_options) }
|
6
|
+
|
7
|
+
context '#log_click_through' do
|
8
|
+
let(:documents) { [first_document, second_document] }
|
9
|
+
let(:first_document_id) { 'id' }
|
10
|
+
let(:first_document) { { 'id' => first_document_id } }
|
11
|
+
let(:second_document_id) { 'another_id' }
|
12
|
+
let(:second_document) { { 'id' => second_document_id } }
|
13
|
+
|
14
|
+
before { client.index_documents(engine_name, documents) }
|
15
|
+
|
16
|
+
subject do
|
17
|
+
client.log_click_through(
|
18
|
+
engine_name,
|
19
|
+
:query => 'cat videos',
|
20
|
+
:document_id => first_document_id,
|
21
|
+
:request_id => 'e4c4dea0bd7ad3d2f676575ef16dc7d2',
|
22
|
+
:tags => ['firefox', 'web browser']
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'will log a click' do
|
27
|
+
expect(subject[0]['id']).not_to(be_empty)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/spec/client_spec.rb
CHANGED
@@ -2,42 +2,9 @@ require 'config_helper'
|
|
2
2
|
require 'securerandom'
|
3
3
|
|
4
4
|
describe Elastic::AppSearch::Client do
|
5
|
-
let(:engine_name) { "ruby-client-test-#{SecureRandom.hex}" }
|
6
|
-
|
7
5
|
include_context 'App Search Credentials'
|
8
6
|
let(:client) { Elastic::AppSearch::Client.new(client_options) }
|
9
7
|
|
10
|
-
before(:all) do
|
11
|
-
# Bootstraps a static engine for 'read-only' options that require indexing
|
12
|
-
# across the test suite
|
13
|
-
@static_engine_name = "ruby-client-test-static-#{SecureRandom.hex}"
|
14
|
-
as_api_key = ConfigHelper.get_as_api_key
|
15
|
-
as_host_identifier = ConfigHelper.get_as_host_identifier
|
16
|
-
as_api_endpoint = ConfigHelper.get_as_api_endpoint
|
17
|
-
client_options = ConfigHelper.get_client_options(as_api_key, as_host_identifier, as_api_endpoint)
|
18
|
-
@static_client = Elastic::AppSearch::Client.new(client_options)
|
19
|
-
@static_client.create_engine(@static_engine_name)
|
20
|
-
|
21
|
-
@document1 = { 'id' => '1', 'title' => 'The Great Gatsby' }
|
22
|
-
@document2 = { 'id' => '2', 'title' => 'Catcher in the Rye' }
|
23
|
-
@documents = [@document1, @document2]
|
24
|
-
@static_client.index_documents(@static_engine_name, @documents)
|
25
|
-
|
26
|
-
# Wait until documents are indexed
|
27
|
-
start = Time.now
|
28
|
-
ready = false
|
29
|
-
until (ready)
|
30
|
-
sleep(3)
|
31
|
-
results = @static_client.search(@static_engine_name, '')
|
32
|
-
ready = true if results['results'].length == 2
|
33
|
-
ready = true if (Time.now - start).to_i >= 120 # Time out after 2 minutes
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
after(:all) do
|
38
|
-
@static_client.destroy_engine(@static_engine_name)
|
39
|
-
end
|
40
|
-
|
41
8
|
describe '#create_signed_search_key' do
|
42
9
|
let(:key) { 'private-xxxxxxxxxxxxxxxxxxxx' }
|
43
10
|
let(:api_key_name) { 'private-key' }
|
@@ -52,9 +19,9 @@ describe Elastic::AppSearch::Client do
|
|
52
19
|
end
|
53
20
|
|
54
21
|
it 'should build a valid jwt' do
|
55
|
-
decoded_token = JWT.decode
|
56
|
-
expect(decoded_token[0]['api_key_name']).to
|
57
|
-
expect(decoded_token[0]['query']).to
|
22
|
+
decoded_token = JWT.decode(subject, key, true, :algorithm => 'HS256')
|
23
|
+
expect(decoded_token[0]['api_key_name']).to(eq(api_key_name))
|
24
|
+
expect(decoded_token[0]['query']).to(eq('cat'))
|
58
25
|
end
|
59
26
|
end
|
60
27
|
|
@@ -62,426 +29,15 @@ describe Elastic::AppSearch::Client do
|
|
62
29
|
it 'should include client name and version in headers' do
|
63
30
|
stub_request(:any, "#{client_options[:host_identifier]}.api.swiftype.com/api/as/v1/engines")
|
64
31
|
client.list_engines
|
65
|
-
expect(WebMock).to
|
32
|
+
expect(WebMock).to(
|
33
|
+
have_requested(:get, "https://#{client_options[:host_identifier]}.api.swiftype.com/api/as/v1/engines")
|
66
34
|
.with(
|
67
35
|
:headers => {
|
68
36
|
'X-Swiftype-Client' => 'elastic-app-search-ruby',
|
69
37
|
'X-Swiftype-Client-Version' => Elastic::AppSearch::VERSION
|
70
38
|
}
|
71
39
|
)
|
72
|
-
|
73
|
-
end
|
74
|
-
|
75
|
-
context 'Documents' do
|
76
|
-
let(:document) { { 'url' => 'http://www.youtube.com/watch?v=v1uyQZNg2vE' } }
|
77
|
-
|
78
|
-
before do
|
79
|
-
client.create_engine(engine_name) rescue Elastic::AppSearch::BadRequest
|
80
|
-
end
|
81
|
-
|
82
|
-
after do
|
83
|
-
client.destroy_engine(engine_name) rescue Elastic::AppSearch::NonExistentRecord
|
84
|
-
end
|
85
|
-
|
86
|
-
describe '#index_document' do
|
87
|
-
subject { client.index_document(engine_name, document) }
|
88
|
-
|
89
|
-
it 'should return a processed document status hash' do
|
90
|
-
expect(subject).to match('id' => anything)
|
91
|
-
end
|
92
|
-
|
93
|
-
context 'when the document has an id' do
|
94
|
-
let(:id) { 'some_id' }
|
95
|
-
let(:document) { { 'id' => id, 'url' => 'http://www.youtube.com/watch?v=v1uyQZNg2vE' } }
|
96
|
-
|
97
|
-
it 'should return a processed document status hash with the same id' do
|
98
|
-
expect(subject).to eq('id' => id)
|
99
|
-
end
|
100
|
-
end
|
101
|
-
|
102
|
-
context 'when a document has processing errors' do
|
103
|
-
let(:document) { { 'id' => 'too long' * 100 } }
|
104
|
-
|
105
|
-
it 'should raise an error when the API returns errors in the response' do
|
106
|
-
expect do
|
107
|
-
subject
|
108
|
-
end.to raise_error(Elastic::AppSearch::InvalidDocument, /Invalid field/)
|
109
|
-
end
|
110
|
-
end
|
111
|
-
|
112
|
-
context 'when a document has a Ruby Time object' do
|
113
|
-
let(:time_rfc3339) { '2018-01-01T01:01:01+00:00' }
|
114
|
-
let(:time_object) { Time.parse(time_rfc3339) }
|
115
|
-
let(:document) { { 'created_at' => time_object } }
|
116
|
-
|
117
|
-
it 'should serialize the time object in RFC 3339' do
|
118
|
-
response = subject
|
119
|
-
expect(response).to have_key('id')
|
120
|
-
document_id = response.fetch('id')
|
121
|
-
expect do
|
122
|
-
documents = client.get_documents(engine_name, [document_id])
|
123
|
-
expect(documents.size).to eq(1)
|
124
|
-
expect(documents.first['created_at']).to eq(time_rfc3339)
|
125
|
-
end.to_not raise_error
|
126
|
-
end
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
describe '#index_documents' do
|
131
|
-
let(:documents) { [document, second_document] }
|
132
|
-
let(:second_document_id) { 'another_id' }
|
133
|
-
let(:second_document) { { 'id' => second_document_id, 'url' => 'https://www.youtube.com/watch?v=9T1vfsHYiKY' } }
|
134
|
-
subject { client.index_documents(engine_name, documents) }
|
135
|
-
|
136
|
-
it 'should return an array of document status hashes' do
|
137
|
-
expect(subject).to match(
|
138
|
-
[
|
139
|
-
{ 'id' => anything, 'errors' => [] },
|
140
|
-
{ 'id' => second_document_id, 'errors' => [] }
|
141
|
-
]
|
142
|
-
)
|
143
|
-
end
|
144
|
-
|
145
|
-
context 'when one of the documents has processing errors' do
|
146
|
-
let(:second_document) { { 'id' => 'too long' * 100 } }
|
147
|
-
|
148
|
-
it 'should return respective errors in an array of document processing hashes' do
|
149
|
-
expect(subject).to match(
|
150
|
-
[
|
151
|
-
{ 'id' => anything, 'errors' => [] },
|
152
|
-
{ 'id' => anything, 'errors' => ['Invalid field type: id must be less than 800 characters'] },
|
153
|
-
]
|
154
|
-
)
|
155
|
-
end
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
describe '#update_documents' do
|
160
|
-
let(:documents) { [document, second_document] }
|
161
|
-
let(:second_document_id) { 'another_id' }
|
162
|
-
let(:second_document) { { 'id' => second_document_id, 'url' => 'https://www.youtube.com/watch?v=9T1vfsHYiKY' } }
|
163
|
-
let(:updates) do
|
164
|
-
[
|
165
|
-
{
|
166
|
-
'id' => second_document_id,
|
167
|
-
'url' => 'https://www.example.com'
|
168
|
-
}
|
169
|
-
]
|
170
|
-
end
|
171
|
-
|
172
|
-
subject { client.update_documents(engine_name, updates) }
|
173
|
-
|
174
|
-
before do
|
175
|
-
client.index_documents(engine_name, documents)
|
176
|
-
end
|
177
|
-
|
178
|
-
# Note that since indexing a document takes up to a minute,
|
179
|
-
# we don't expect this to succeed, so we simply verify that
|
180
|
-
# the request responded with the correct 'id', even though
|
181
|
-
# the 'errors' object likely contains errors.
|
182
|
-
it 'should update existing documents' do
|
183
|
-
expect(subject).to match(['id' => second_document_id, 'errors' => anything])
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
describe '#get_documents' do
|
188
|
-
let(:documents) { [first_document, second_document] }
|
189
|
-
let(:first_document_id) { 'id' }
|
190
|
-
let(:first_document) { { 'id' => first_document_id, 'url' => 'https://www.youtube.com/watch?v=v1uyQZNg2vE' } }
|
191
|
-
let(:second_document_id) { 'another_id' }
|
192
|
-
let(:second_document) { { 'id' => second_document_id, 'url' => 'https://www.youtube.com/watch?v=9T1vfsHYiKY' } }
|
193
|
-
|
194
|
-
subject { client.get_documents(engine_name, [first_document_id, second_document_id]) }
|
195
|
-
|
196
|
-
before do
|
197
|
-
client.index_documents(engine_name, documents)
|
198
|
-
end
|
199
|
-
|
200
|
-
it 'will return documents by id' do
|
201
|
-
response = subject
|
202
|
-
expect(response.size).to eq(2)
|
203
|
-
expect(response[0]['id']).to eq(first_document_id)
|
204
|
-
expect(response[1]['id']).to eq(second_document_id)
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
describe '#list_documents' do
|
209
|
-
let(:documents) { [first_document, second_document] }
|
210
|
-
let(:first_document_id) { 'id' }
|
211
|
-
let(:first_document) { { 'id' => first_document_id, 'url' => 'https://www.youtube.com/watch?v=v1uyQZNg2vE' } }
|
212
|
-
let(:second_document_id) { 'another_id' }
|
213
|
-
let(:second_document) { { 'id' => second_document_id, 'url' => 'https://www.youtube.com/watch?v=9T1vfsHYiKY' } }
|
214
|
-
|
215
|
-
before do
|
216
|
-
client.index_documents(engine_name, documents)
|
217
|
-
end
|
218
|
-
|
219
|
-
context 'when no options are specified' do
|
220
|
-
it 'will return all documents' do
|
221
|
-
response = client.list_documents(engine_name)
|
222
|
-
expect(response['results'].size).to eq(2)
|
223
|
-
expect(response['results'][0]['id']).to eq(first_document_id)
|
224
|
-
expect(response['results'][1]['id']).to eq(second_document_id)
|
225
|
-
end
|
226
|
-
end
|
227
|
-
|
228
|
-
context 'when options are specified' do
|
229
|
-
it 'will return all documents' do
|
230
|
-
response = client.list_documents(engine_name, :page => { :size => 1, :current => 2 })
|
231
|
-
expect(response['results'].size).to eq(1)
|
232
|
-
expect(response['results'][0]['id']).to eq(second_document_id)
|
233
|
-
end
|
234
|
-
end
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
context 'Search' do
|
239
|
-
describe '#search' do
|
240
|
-
subject { @static_client.search(@static_engine_name, query, options) }
|
241
|
-
let(:query) { '' }
|
242
|
-
let(:options) { { 'page' => { 'size' => 2 } } }
|
243
|
-
|
244
|
-
it 'should execute a search query' do
|
245
|
-
expect(subject).to match(
|
246
|
-
'meta' => anything,
|
247
|
-
'results' => [anything, anything]
|
248
|
-
)
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
describe '#multi_search' do
|
253
|
-
subject { @static_client.multi_search(@static_engine_name, queries) }
|
254
|
-
|
255
|
-
context 'when options are provided' do
|
256
|
-
let(:queries) do
|
257
|
-
[
|
258
|
-
{ 'query' => 'gatsby', 'options' => { 'page' => { 'size' => 1 } } },
|
259
|
-
{ 'query' => 'catcher', 'options' => { 'page' => { 'size' => 1 } } }
|
260
|
-
]
|
261
|
-
end
|
262
|
-
|
263
|
-
it 'should execute a multi search query' do
|
264
|
-
response = subject
|
265
|
-
expect(response).to match(
|
266
|
-
[
|
267
|
-
{
|
268
|
-
'meta' => anything,
|
269
|
-
'results' => [{ 'id' => { 'raw' => '1' }, 'title' => anything, '_meta' => anything }]
|
270
|
-
},
|
271
|
-
{
|
272
|
-
'meta' => anything,
|
273
|
-
'results' => [{ 'id' => { 'raw' => '2' }, 'title' => anything, '_meta' => anything }]
|
274
|
-
}
|
275
|
-
]
|
276
|
-
)
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
context 'when options are omitted' do
|
281
|
-
let(:queries) do
|
282
|
-
[
|
283
|
-
{ 'query' => 'gatsby' },
|
284
|
-
{ 'query' => 'catcher' }
|
285
|
-
]
|
286
|
-
end
|
287
|
-
|
288
|
-
it 'should execute a multi search query' do
|
289
|
-
response = subject
|
290
|
-
expect(response).to match(
|
291
|
-
[
|
292
|
-
{
|
293
|
-
'meta' => anything,
|
294
|
-
'results' => [{ 'id' => { 'raw' => '1' }, 'title' => anything, '_meta' => anything }]
|
295
|
-
},
|
296
|
-
{
|
297
|
-
'meta' => anything,
|
298
|
-
'results' => [{ 'id' => { 'raw' => '2' }, 'title' => anything, '_meta' => anything }]
|
299
|
-
}
|
300
|
-
]
|
301
|
-
)
|
302
|
-
end
|
303
|
-
end
|
304
|
-
|
305
|
-
context 'when a search is bad' do
|
306
|
-
let(:queries) do
|
307
|
-
[
|
308
|
-
{
|
309
|
-
'query' => 'cat',
|
310
|
-
'options' => { 'search_fields' => { 'taco' => {} } }
|
311
|
-
}, {
|
312
|
-
'query' => 'dog',
|
313
|
-
'options' => { 'search_fields' => { 'body' => {} } }
|
314
|
-
}
|
315
|
-
]
|
316
|
-
end
|
317
|
-
|
318
|
-
it 'should throw an appropriate error' do
|
319
|
-
expect { subject }.to raise_error do |e|
|
320
|
-
expect(e).to be_a(Elastic::AppSearch::BadRequest)
|
321
|
-
expect(e.errors).to eq(['Search fields contains invalid field: taco', 'Search fields contains invalid field: body'])
|
322
|
-
end
|
323
|
-
end
|
324
|
-
end
|
325
|
-
end
|
326
|
-
end
|
327
|
-
|
328
|
-
context 'QuerySuggest' do
|
329
|
-
describe '#query_suggestion' do
|
330
|
-
let(:query) { 'cat' }
|
331
|
-
let(:options) { { :size => 3, :types => { :documents => { :fields => ['title'] } } } }
|
332
|
-
|
333
|
-
context 'when options are provided' do
|
334
|
-
subject { @static_client.query_suggestion(@static_engine_name, query, options) }
|
335
|
-
|
336
|
-
it 'should request query suggestions' do
|
337
|
-
expect(subject).to match(
|
338
|
-
'meta' => anything,
|
339
|
-
'results' => anything
|
340
|
-
)
|
341
|
-
end
|
342
|
-
end
|
343
|
-
|
344
|
-
context 'when options are omitted' do
|
345
|
-
subject { @static_client.query_suggestion(@static_engine_name, query) }
|
346
|
-
|
347
|
-
it 'should request query suggestions' do
|
348
|
-
expect(subject).to match(
|
349
|
-
'meta' => anything,
|
350
|
-
'results' => anything
|
351
|
-
)
|
352
|
-
end
|
353
|
-
end
|
354
|
-
end
|
355
|
-
end
|
356
|
-
|
357
|
-
context 'SearchSettings' do
|
358
|
-
let(:default_settings) { {
|
359
|
-
"search_fields" => {
|
360
|
-
"id" => {
|
361
|
-
"weight" => 1
|
362
|
-
}
|
363
|
-
},
|
364
|
-
"result_fields" => {"id"=>{"raw"=>{}}},
|
365
|
-
"boosts" => {}
|
366
|
-
} }
|
367
|
-
|
368
|
-
let(:updated_settings) { {
|
369
|
-
"search_fields" => {
|
370
|
-
"id" => {
|
371
|
-
"weight" => 3
|
372
|
-
}
|
373
|
-
},
|
374
|
-
"result_fields" => {"id"=>{"raw"=>{}}},
|
375
|
-
"boosts" => {}
|
376
|
-
} }
|
377
|
-
|
378
|
-
before(:each) do
|
379
|
-
client.create_engine(engine_name) rescue Elastic::AppSearch::BadRequest
|
380
|
-
end
|
381
|
-
|
382
|
-
after(:each) do
|
383
|
-
client.destroy_engine(engine_name) rescue Elastic::AppSearch::NonExistentRecord
|
384
|
-
end
|
385
|
-
|
386
|
-
describe '#show_settings' do
|
387
|
-
subject { client.show_settings(engine_name) }
|
388
|
-
|
389
|
-
it 'should return default settings' do
|
390
|
-
expect(subject).to match(default_settings)
|
391
|
-
end
|
392
|
-
end
|
393
|
-
|
394
|
-
describe '#update_settings' do
|
395
|
-
subject { client.show_settings(engine_name) }
|
396
|
-
|
397
|
-
before do
|
398
|
-
client.update_settings(engine_name, updated_settings)
|
399
|
-
end
|
400
|
-
|
401
|
-
it 'should update search settings' do
|
402
|
-
expect(subject).to match(updated_settings)
|
403
|
-
end
|
404
|
-
end
|
405
|
-
|
406
|
-
describe '#reset_settings' do
|
407
|
-
subject { client.show_settings(engine_name) }
|
408
|
-
|
409
|
-
before do
|
410
|
-
client.update_settings(engine_name, updated_settings)
|
411
|
-
client.reset_settings(engine_name)
|
412
|
-
end
|
413
|
-
|
414
|
-
it 'should reset search settings' do
|
415
|
-
expect(subject).to match(default_settings)
|
416
|
-
end
|
417
|
-
end
|
418
|
-
end
|
419
|
-
|
420
|
-
context 'Engines' do
|
421
|
-
after do
|
422
|
-
client.destroy_engine(engine_name) rescue Elastic::AppSearch::NonExistentRecord
|
423
|
-
end
|
424
|
-
|
425
|
-
context '#create_engine' do
|
426
|
-
it 'should create an engine when given a right set of parameters' do
|
427
|
-
expect { client.get_engine(engine_name) }.to raise_error(Elastic::AppSearch::NonExistentRecord)
|
428
|
-
client.create_engine(engine_name)
|
429
|
-
expect { client.get_engine(engine_name) }.to_not raise_error
|
430
|
-
end
|
431
|
-
|
432
|
-
it 'should accept an optional language parameter' do
|
433
|
-
expect { client.get_engine(engine_name) }.to raise_error(Elastic::AppSearch::NonExistentRecord)
|
434
|
-
client.create_engine(engine_name, 'da')
|
435
|
-
expect(client.get_engine(engine_name)).to match('name' => anything, 'type' => anything, 'language' => 'da')
|
436
|
-
end
|
437
|
-
|
438
|
-
it 'should return an engine object' do
|
439
|
-
engine = client.create_engine(engine_name)
|
440
|
-
expect(engine).to be_kind_of(Hash)
|
441
|
-
expect(engine['name']).to eq(engine_name)
|
442
|
-
end
|
443
|
-
|
444
|
-
it 'should return an error when the engine name has already been taken' do
|
445
|
-
client.create_engine(engine_name)
|
446
|
-
expect { client.create_engine(engine_name) }.to raise_error do |e|
|
447
|
-
expect(e).to be_a(Elastic::AppSearch::BadRequest)
|
448
|
-
expect(e.errors).to eq(['Name is already taken'])
|
449
|
-
end
|
450
|
-
end
|
451
|
-
end
|
452
|
-
|
453
|
-
context '#list_engines' do
|
454
|
-
it 'should return an array with a list of engines' do
|
455
|
-
expect(client.list_engines['results']).to be_an(Array)
|
456
|
-
end
|
457
|
-
|
458
|
-
it 'should include the engine name in listed objects' do
|
459
|
-
client.create_engine(engine_name)
|
460
|
-
|
461
|
-
engines = client.list_engines['results']
|
462
|
-
expect(engines.find { |e| e['name'] == engine_name }).to_not be_nil
|
463
|
-
end
|
464
|
-
|
465
|
-
it 'should include the engine name in listed objects with pagination' do
|
466
|
-
client.create_engine(engine_name)
|
467
|
-
|
468
|
-
engines = client.list_engines(:current => 1, :size => 20)['results']
|
469
|
-
expect(engines.find { |e| e['name'] == engine_name }).to_not be_nil
|
470
|
-
end
|
471
|
-
end
|
472
|
-
|
473
|
-
context '#destroy_engine' do
|
474
|
-
it 'should destroy the engine if it exists' do
|
475
|
-
client.create_engine(engine_name)
|
476
|
-
expect { client.get_engine(engine_name) }.to_not raise_error
|
477
|
-
|
478
|
-
client.destroy_engine(engine_name)
|
479
|
-
expect { client.get_engine(engine_name) }.to raise_error(Elastic::AppSearch::NonExistentRecord)
|
480
|
-
end
|
481
|
-
|
482
|
-
it 'should raise an error if the engine does not exist' do
|
483
|
-
expect { client.destroy_engine(engine_name) }.to raise_error(Elastic::AppSearch::NonExistentRecord)
|
484
|
-
end
|
40
|
+
)
|
485
41
|
end
|
486
42
|
end
|
487
43
|
|
@@ -489,12 +45,12 @@ describe Elastic::AppSearch::Client do
|
|
489
45
|
context 'host_identifier' do
|
490
46
|
it 'sets the base url correctly' do
|
491
47
|
client = Elastic::AppSearch::Client.new(:host_identifier => 'host-asdf', :api_key => 'foo')
|
492
|
-
expect(client.api_endpoint).to
|
48
|
+
expect(client.api_endpoint).to(eq('https://host-asdf.api.swiftype.com/api/as/v1/'))
|
493
49
|
end
|
494
50
|
|
495
51
|
it 'sets the base url correctly using deprecated as_host_key' do
|
496
52
|
client = Elastic::AppSearch::Client.new(:account_host_key => 'host-asdf', :api_key => 'foo')
|
497
|
-
expect(client.api_endpoint).to
|
53
|
+
expect(client.api_endpoint).to(eq('https://host-asdf.api.swiftype.com/api/as/v1/'))
|
498
54
|
end
|
499
55
|
end
|
500
56
|
end
|