swiftype-app-search 0.3.0 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +49 -57
- data/lib/swiftype-app-search/client/documents.rb +26 -2
- data/lib/swiftype-app-search/client/engines.rb +4 -2
- data/lib/swiftype-app-search/client/search.rb +20 -1
- data/lib/swiftype-app-search/version.rb +1 -1
- data/spec/client_spec.rb +143 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0889b18cde354daea10527a1e192cd972e0d7c539fa4bbee73b2683de3b3822
|
4
|
+
data.tar.gz: 0b65d19dcf830652d055ead107abdc554dcb28f3f5d74d528d2be5d53cf15d63
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cfe38cefe4f27e5d3056041b6166ce7779f759b77600d10bf345959dfaa2661f76543d44fbaac028814da267620824a5112334b424c18c6b9ed3c1f9bdd49fe8
|
7
|
+
data.tar.gz: 1ceada4a0bbb951a2c4a3885f683a3d5fb148569cdeb386ce9a224d7621d0402a0e33a3e424fada53b017efa9d5c5efc3b2c837a51bca6eff6a411a4a70e5803
|
data/README.md
CHANGED
@@ -10,7 +10,7 @@ To install the gem, execute:
|
|
10
10
|
gem install swiftype-app-search
|
11
11
|
```
|
12
12
|
|
13
|
-
Or place `gem 'swiftype-app-search', '~> 0.
|
13
|
+
Or place `gem 'swiftype-app-search', '~> 0.4.0` in your `Gemfile` and run `bundle install`.
|
14
14
|
|
15
15
|
## Usage
|
16
16
|
|
@@ -42,15 +42,10 @@ document = {
|
|
42
42
|
:body => 'A wonderful video of a magnificent cat.'
|
43
43
|
}
|
44
44
|
|
45
|
-
|
46
|
-
response = client.index_document(engine_name, document)
|
47
|
-
puts response
|
48
|
-
rescue SwiftypeAppSearch::ClientException => e
|
49
|
-
puts e
|
50
|
-
end
|
45
|
+
client.index_document(engine_name, document)
|
51
46
|
```
|
52
47
|
|
53
|
-
#### Indexing: Creating or
|
48
|
+
#### Indexing: Creating or Replacing Documents
|
54
49
|
|
55
50
|
```ruby
|
56
51
|
engine_name = 'favorite-videos'
|
@@ -69,26 +64,37 @@ documents = [
|
|
69
64
|
}
|
70
65
|
]
|
71
66
|
|
72
|
-
|
73
|
-
response = client.index_documents(engine_name, documents)
|
74
|
-
puts response
|
75
|
-
rescue SwiftypeAppSearch::ClientException => e
|
76
|
-
puts e
|
77
|
-
end
|
67
|
+
client.index_documents(engine_name, documents)
|
78
68
|
```
|
79
69
|
|
80
|
-
####
|
70
|
+
#### Indexing: Updating Documents (Partial Updates)
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
engine_name = 'favorite-videos'
|
74
|
+
documents = [
|
75
|
+
{
|
76
|
+
:id => 'INscMGmhmX4',
|
77
|
+
:title => 'Updated title'
|
78
|
+
}
|
79
|
+
]
|
80
|
+
|
81
|
+
client.update_documents(engine_name, documents)
|
82
|
+
```
|
83
|
+
|
84
|
+
#### Retrieving Documents
|
81
85
|
|
82
86
|
```ruby
|
83
87
|
engine_name = 'favorite-videos'
|
84
88
|
document_ids = ['INscMGmhmX4', 'JNDFojsd02']
|
85
89
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
90
|
+
client.get_documents(engine_name, document_ids)
|
91
|
+
```
|
92
|
+
|
93
|
+
#### Listing Documents
|
94
|
+
```ruby
|
95
|
+
engine_name = 'favorite-videos'
|
96
|
+
|
97
|
+
client.list_documents(engine_name)
|
92
98
|
```
|
93
99
|
|
94
100
|
#### Destroying Documents
|
@@ -97,23 +103,13 @@ end
|
|
97
103
|
engine_name = 'favorite-videos'
|
98
104
|
document_ids = ['INscMGmhmX4', 'JNDFojsd02']
|
99
105
|
|
100
|
-
|
101
|
-
response = client.destroy_documents(engine_name, document_ids)
|
102
|
-
puts response
|
103
|
-
rescue SwiftypeAppSearch::ClientException => e
|
104
|
-
puts e
|
105
|
-
end
|
106
|
+
client.destroy_documents(engine_name, document_ids)
|
106
107
|
```
|
107
108
|
|
108
109
|
#### Listing Engines
|
109
110
|
|
110
111
|
```ruby
|
111
|
-
|
112
|
-
response = client.list_engines
|
113
|
-
puts response
|
114
|
-
rescue SwiftypeAppSearch::ClientException => e
|
115
|
-
puts e
|
116
|
-
end
|
112
|
+
client.list_engines
|
117
113
|
```
|
118
114
|
|
119
115
|
#### Retrieving Engines
|
@@ -121,12 +117,7 @@ end
|
|
121
117
|
```ruby
|
122
118
|
engine_name = 'favorite-videos'
|
123
119
|
|
124
|
-
|
125
|
-
response = client.get_engine(engine_name)
|
126
|
-
puts response
|
127
|
-
rescue SwiftypeAppSearch::ClientException => e
|
128
|
-
puts e
|
129
|
-
end
|
120
|
+
client.get_engine(engine_name)
|
130
121
|
```
|
131
122
|
|
132
123
|
#### Creating Engines
|
@@ -134,12 +125,7 @@ end
|
|
134
125
|
```ruby
|
135
126
|
engine_name = 'favorite-videos'
|
136
127
|
|
137
|
-
|
138
|
-
response = client.create_engine(engine_name)
|
139
|
-
puts response
|
140
|
-
rescue SwiftypeAppSearch::ClientException => e
|
141
|
-
puts e
|
142
|
-
end
|
128
|
+
client.create_engine(engine_name)
|
143
129
|
```
|
144
130
|
|
145
131
|
#### Destroying Engines
|
@@ -147,12 +133,7 @@ end
|
|
147
133
|
```ruby
|
148
134
|
engine_name = 'favorite-videos'
|
149
135
|
|
150
|
-
|
151
|
-
response = client.destroy_engine(engine_name)
|
152
|
-
puts response
|
153
|
-
rescue SwiftypeAppSearch::ClientException => e
|
154
|
-
puts e
|
155
|
-
end
|
136
|
+
client.destroy_engine(engine_name)
|
156
137
|
```
|
157
138
|
|
158
139
|
#### Searching
|
@@ -164,12 +145,23 @@ search_fields = { :title => {} }
|
|
164
145
|
result_fields = { :title => { :raw => {} } }
|
165
146
|
options = { :search_fields => search_fields, :result_fields => result_fields }
|
166
147
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
148
|
+
client.search(engine_name, query, options)
|
149
|
+
```
|
150
|
+
|
151
|
+
#### Multi-Search
|
152
|
+
|
153
|
+
```ruby
|
154
|
+
engine_name = 'favorite-videos'
|
155
|
+
|
156
|
+
queries = [{
|
157
|
+
:query => 'cat',
|
158
|
+
:options => { :search_fields => { :title => {} }}
|
159
|
+
},{
|
160
|
+
:query => 'dog',
|
161
|
+
:options => { :search_fields => { :body => {} }}
|
162
|
+
}]
|
163
|
+
|
164
|
+
client.multi_search(engine_name, queries)
|
173
165
|
```
|
174
166
|
|
175
167
|
## Running Tests
|
@@ -5,13 +5,23 @@ module SwiftypeAppSearch
|
|
5
5
|
class Client
|
6
6
|
module Documents
|
7
7
|
|
8
|
-
# Retrieve Documents from the API
|
8
|
+
# Retrieve all Documents from the API for the {App Search API}[https://swiftype.com/documentation/app-search/]
|
9
9
|
#
|
10
10
|
# @param [String] engine_name the unique Engine name
|
11
|
-
# @
|
11
|
+
# @option options see the {App Search API}[https://swiftype.com/documentation/app-search/] for supported options.
|
12
12
|
#
|
13
13
|
# @return [Array<Hash>] an Array of Documents
|
14
|
+
def list_documents(engine_name, options = {})
|
15
|
+
params = Utils.symbolize_keys(options)
|
16
|
+
request(:get, "engines/#{engine_name}/documents/list", params)
|
17
|
+
end
|
14
18
|
|
19
|
+
# Retrieve Documents from the API by IDs for the {App Search API}[https://swiftype.com/documentation/app-search/]
|
20
|
+
#
|
21
|
+
# @param [String] engine_name the unique Engine name
|
22
|
+
# @param [Array<String>] ids an Array of Document IDs
|
23
|
+
#
|
24
|
+
# @return [Hash] list results
|
15
25
|
def get_documents(engine_name, ids)
|
16
26
|
get("engines/#{engine_name}/documents", ids)
|
17
27
|
end
|
@@ -46,6 +56,20 @@ module SwiftypeAppSearch
|
|
46
56
|
post("engines/#{engine_name}/documents", documents)
|
47
57
|
end
|
48
58
|
|
59
|
+
# Update a batch of documents using the {App Search API}[https://swiftype.com/documentation/app-search/].
|
60
|
+
#
|
61
|
+
# @param [String] engine_name the unique Engine name
|
62
|
+
# @param [Array] documents an Array of Document Hashes including valid ids
|
63
|
+
#
|
64
|
+
# @return [Array<Hash>] an Array of processed Document Status hashes
|
65
|
+
#
|
66
|
+
# @raise [SwiftypeAppSearch::InvalidDocument] when any documents have processing errors returned from the api
|
67
|
+
# @raise [Timeout::Error] when timeout expires waiting for statuses
|
68
|
+
def update_documents(engine_name, documents)
|
69
|
+
documents.map! { |document| normalize_document(document) }
|
70
|
+
patch("engines/#{engine_name}/documents", documents)
|
71
|
+
end
|
72
|
+
|
49
73
|
# Destroy a batch of documents given a list of IDs
|
50
74
|
#
|
51
75
|
# @param [Array<String>] ids an Array of Document IDs
|
@@ -11,8 +11,10 @@ module SwiftypeAppSearch
|
|
11
11
|
get("engines/#{engine_name}")
|
12
12
|
end
|
13
13
|
|
14
|
-
def create_engine(engine_name)
|
15
|
-
|
14
|
+
def create_engine(engine_name, language = nil)
|
15
|
+
params = { :name => engine_name }
|
16
|
+
params[:language] = language if language
|
17
|
+
post("engines", params)
|
16
18
|
end
|
17
19
|
|
18
20
|
def destroy_engine(engine_name)
|
@@ -7,11 +7,30 @@ module SwiftypeAppSearch
|
|
7
7
|
# @param [String] query the search query
|
8
8
|
# @option options see the {App Search API}[https://swiftype.com/documentation/app-search/] for supported search options.
|
9
9
|
#
|
10
|
-
# @return [
|
10
|
+
# @return [Hash] search results
|
11
11
|
def search(engine_name, query, options = {})
|
12
12
|
params = Utils.symbolize_keys(options).merge(:query => query)
|
13
13
|
request(:post, "engines/#{engine_name}/search", params)
|
14
14
|
end
|
15
|
+
|
16
|
+
# Run multiple searches for documents on a single request
|
17
|
+
#
|
18
|
+
# @param [String] engine_name the unique Engine name
|
19
|
+
# @param [{query: String, options: Hash}] searches to execute
|
20
|
+
# see the {App Search API}[https://swiftype.com/documentation/app-search/] for supported search options.
|
21
|
+
#
|
22
|
+
# @return [Array<Hash>] an Array of searh sesults
|
23
|
+
def multi_search(engine_name, searches)
|
24
|
+
params = searches.map do |search|
|
25
|
+
search = Utils.symbolize_keys(search)
|
26
|
+
query = search[:query]
|
27
|
+
options = search[:options] || {}
|
28
|
+
Utils.symbolize_keys(options).merge(:query => query)
|
29
|
+
end
|
30
|
+
request(:post, "engines/#{engine_name}/multi_search", {
|
31
|
+
queries: params
|
32
|
+
})
|
33
|
+
end
|
15
34
|
end
|
16
35
|
end
|
17
36
|
end
|
data/spec/client_spec.rb
CHANGED
@@ -98,6 +98,143 @@ describe SwiftypeAppSearch::Client do
|
|
98
98
|
end
|
99
99
|
end
|
100
100
|
end
|
101
|
+
|
102
|
+
describe '#update_documents' do
|
103
|
+
let(:documents) { [document, second_document] }
|
104
|
+
let(:second_document_id) { 'another_id' }
|
105
|
+
let(:second_document) { { 'id' => second_document_id, 'url' => 'https://www.youtube.com/watch?v=9T1vfsHYiKY' } }
|
106
|
+
let(:updates) { [ {
|
107
|
+
'id' => second_document_id,
|
108
|
+
'url' => 'https://www.example.com'
|
109
|
+
} ] }
|
110
|
+
|
111
|
+
subject { client.update_documents(engine_name, updates) }
|
112
|
+
|
113
|
+
before do
|
114
|
+
client.index_documents(engine_name, documents)
|
115
|
+
end
|
116
|
+
|
117
|
+
# Note that since indexing a document takes up to a minute,
|
118
|
+
# we don't expect this to succeed, so we simply verify that
|
119
|
+
# the request responded with the correct 'id', even though
|
120
|
+
# the 'errors' object likely contains errors.
|
121
|
+
it 'should update existing documents' do
|
122
|
+
response = subject
|
123
|
+
expect(subject).to match(['id' => second_document_id, 'errors' => anything])
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
describe '#get_documents' do
|
128
|
+
let(:documents) { [first_document, second_document] }
|
129
|
+
let(:first_document_id) { 'id' }
|
130
|
+
let(:first_document) { { 'id' => first_document_id, 'url' => 'https://www.youtube.com/watch?v=v1uyQZNg2vE' } }
|
131
|
+
let(:second_document_id) { 'another_id' }
|
132
|
+
let(:second_document) { { 'id' => second_document_id, 'url' => 'https://www.youtube.com/watch?v=9T1vfsHYiKY' } }
|
133
|
+
|
134
|
+
subject { client.get_documents(engine_name, [first_document_id, second_document_id]) }
|
135
|
+
|
136
|
+
before do
|
137
|
+
client.index_documents(engine_name, documents)
|
138
|
+
end
|
139
|
+
|
140
|
+
it 'will return documents by id' do
|
141
|
+
response = subject
|
142
|
+
expect(response.size).to eq(2)
|
143
|
+
expect(response[0]['id']).to eq(first_document_id)
|
144
|
+
expect(response[1]['id']).to eq(second_document_id)
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe '#list_documents' do
|
149
|
+
let(:documents) { [first_document, second_document] }
|
150
|
+
let(:first_document_id) { 'id' }
|
151
|
+
let(:first_document) { { 'id' => first_document_id, 'url' => 'https://www.youtube.com/watch?v=v1uyQZNg2vE' } }
|
152
|
+
let(:second_document_id) { 'another_id' }
|
153
|
+
let(:second_document) { { 'id' => second_document_id, 'url' => 'https://www.youtube.com/watch?v=9T1vfsHYiKY' } }
|
154
|
+
|
155
|
+
before do
|
156
|
+
client.index_documents(engine_name, documents)
|
157
|
+
end
|
158
|
+
|
159
|
+
context 'when no options are specified' do
|
160
|
+
it 'will return all documents' do
|
161
|
+
response = client.list_documents(engine_name)
|
162
|
+
expect(response['results'].size).to eq(2)
|
163
|
+
expect(response['results'][0]['id']).to eq(first_document_id)
|
164
|
+
expect(response['results'][1]['id']).to eq(second_document_id)
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context 'when options are specified' do
|
169
|
+
it 'will return all documents' do
|
170
|
+
response = client.list_documents(engine_name, {page: { size: 1, current: 2}})
|
171
|
+
expect(response['results'].size).to eq(1)
|
172
|
+
expect(response['results'][0]['id']).to eq(second_document_id)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
context 'Search' do
|
179
|
+
# Note that since indexing a document takes up to a minute,
|
180
|
+
# don't actually expect results to be present, just that
|
181
|
+
# the request was made
|
182
|
+
|
183
|
+
before do
|
184
|
+
client.create_engine(engine_name) rescue SwiftypeAppSearch::BadRequest
|
185
|
+
end
|
186
|
+
|
187
|
+
after do
|
188
|
+
client.destroy_engine(engine_name) rescue SwiftypeAppSearch::NonExistentRecord
|
189
|
+
end
|
190
|
+
|
191
|
+
describe '#search' do
|
192
|
+
subject { client.search(engine_name, query, options) }
|
193
|
+
let (:query) { '' }
|
194
|
+
let (:options) { { 'page' => { 'size' => 1 } } }
|
195
|
+
|
196
|
+
it 'should execute a search query' do
|
197
|
+
response = subject
|
198
|
+
expect(response).to have_key('meta')
|
199
|
+
expect(response).to have_key('results')
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
describe '#multi_search' do
|
204
|
+
subject { client.multi_search(engine_name, queries) }
|
205
|
+
|
206
|
+
context 'when options are provided' do
|
207
|
+
let (:queries) { [
|
208
|
+
{'query': 'foo', 'options' => { 'page' => { 'size' => 1 } }},
|
209
|
+
{'query': 'bar', 'options' => { 'page' => { 'size' => 1 } }}
|
210
|
+
] }
|
211
|
+
|
212
|
+
it 'should execute a multi search query' do
|
213
|
+
response = subject
|
214
|
+
expect(response.size).to eq(2)
|
215
|
+
expect(response[0]).to have_key('results')
|
216
|
+
expect(response[0]).to have_key('meta')
|
217
|
+
expect(response[1]).to have_key('results')
|
218
|
+
expect(response[1]).to have_key('meta')
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
context 'when options are omitted' do
|
223
|
+
let (:queries) { [
|
224
|
+
{'query': 'foo' },
|
225
|
+
{'query': 'bar' }
|
226
|
+
] }
|
227
|
+
|
228
|
+
it 'should execute a multi search query' do
|
229
|
+
response = subject
|
230
|
+
expect(response.size).to eq(2)
|
231
|
+
expect(response[0]).to have_key('results')
|
232
|
+
expect(response[0]).to have_key('meta')
|
233
|
+
expect(response[1]).to have_key('results')
|
234
|
+
expect(response[1]).to have_key('meta')
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
101
238
|
end
|
102
239
|
|
103
240
|
context 'Engines' do
|
@@ -112,6 +249,12 @@ describe SwiftypeAppSearch::Client do
|
|
112
249
|
expect { client.get_engine(engine_name) }.to_not raise_error
|
113
250
|
end
|
114
251
|
|
252
|
+
it 'should accept an optional language parameter' do
|
253
|
+
expect { client.get_engine(engine_name) }.to raise_error(SwiftypeAppSearch::NonExistentRecord)
|
254
|
+
client.create_engine(engine_name, 'da')
|
255
|
+
expect(client.get_engine(engine_name)).to match('name' => anything, 'type' => anything, 'language' => 'da')
|
256
|
+
end
|
257
|
+
|
115
258
|
it 'should return an engine object' do
|
116
259
|
engine = client.create_engine(engine_name)
|
117
260
|
expect(engine).to be_kind_of(Hash)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: swiftype-app-search
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Quin Hoxie
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-
|
11
|
+
date: 2018-10-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: awesome_print
|