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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7ed5f865b5826a9e1f6ef4159e8666f40854d88507d5e385ade79843be1ec328
4
- data.tar.gz: 8de8289db41e4b425c88890c7e9ec9d2347b6f234654c0813d9f79b51c40601c
3
+ metadata.gz: c0889b18cde354daea10527a1e192cd972e0d7c539fa4bbee73b2683de3b3822
4
+ data.tar.gz: 0b65d19dcf830652d055ead107abdc554dcb28f3f5d74d528d2be5d53cf15d63
5
5
  SHA512:
6
- metadata.gz: 2fd5aafef38257cae51fc924825020cceb127c980d54c26e6011ee28a3b620d8143fa94e56d49de5fd9e646e3509f2242afbc425da220a013e040d6f6e2aa3f8
7
- data.tar.gz: d78bda22152a9e4046582612c136a63bdd3a18daa0d1a305a847ac04a4f90b077a9805f17f7c638807fba3dd58702143b861fe29158a2032ec6a7c5cadc2c3da
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.1.3` in your `Gemfile` and run `bundle install`.
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
- begin
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 Updating Documents
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
- begin
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
- #### Listing Documents
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
- begin
87
- response = client.get_documents(engine_name, document_ids)
88
- puts response
89
- rescue SwiftypeAppSearch::ClientException => e
90
- puts e
91
- end
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
- begin
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
- begin
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
- begin
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
- begin
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
- begin
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
- begin
168
- response = client.search(engine_name, query, options)
169
- puts response
170
- rescue SwiftypeAppSearch::ClientException => e
171
- puts e
172
- end
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 by IDs for the {App Search API}[https://swiftype.com/documentation/app-search/]
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
- # @param [Array<String>] ids an Array of Document IDs
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
- post("engines", :name => engine_name)
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 [Array<Hash>] an Array of Document destroy result hashes
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
@@ -1,3 +1,3 @@
1
1
  module SwiftypeAppSearch
2
- VERSION = '0.3.0'
2
+ VERSION = '0.4.0'
3
3
  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.3.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-07-12 00:00:00.000000000 Z
11
+ date: 2018-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: awesome_print