elastic-site-search 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/.circleci/config.yml +58 -0
  3. data/.gitignore +10 -0
  4. data/.travis.yml +13 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +201 -0
  7. data/NOTICE.txt +3 -0
  8. data/README.md +418 -0
  9. data/Rakefile +1 -0
  10. data/elastic-site-search.gemspec +26 -0
  11. data/lib/data/ca-bundle.crt +3554 -0
  12. data/lib/elastic/site-search.rb +9 -0
  13. data/lib/elastic/site-search/client.rb +527 -0
  14. data/lib/elastic/site-search/configuration.rb +67 -0
  15. data/lib/elastic/site-search/exceptions.rb +11 -0
  16. data/lib/elastic/site-search/ext/backport-uri.rb +33 -0
  17. data/lib/elastic/site-search/request.rb +156 -0
  18. data/lib/elastic/site-search/result_set.rb +84 -0
  19. data/lib/elastic/site-search/sso.rb +22 -0
  20. data/lib/elastic/site-search/version.rb +5 -0
  21. data/logo-site-search.png +0 -0
  22. data/spec/client_spec.rb +728 -0
  23. data/spec/configuration_spec.rb +37 -0
  24. data/spec/fixtures/vcr/analytics_autoselects.yml +57 -0
  25. data/spec/fixtures/vcr/analytics_autoselects_with_document_type.yml +57 -0
  26. data/spec/fixtures/vcr/analytics_autoselects_with_document_type_and_time_range.yml +57 -0
  27. data/spec/fixtures/vcr/analytics_autoselects_with_time_range.yml +57 -0
  28. data/spec/fixtures/vcr/analytics_clicks.yml +57 -0
  29. data/spec/fixtures/vcr/analytics_clicks_with_document_type.yml +57 -0
  30. data/spec/fixtures/vcr/analytics_clicks_with_document_type_and_time_range.yml +57 -0
  31. data/spec/fixtures/vcr/analytics_clicks_with_time_range.yml +57 -0
  32. data/spec/fixtures/vcr/analytics_searches.yml +57 -0
  33. data/spec/fixtures/vcr/analytics_searches_with_document_type_and_time_range.yml +57 -0
  34. data/spec/fixtures/vcr/analytics_searches_with_time_range.yml +57 -0
  35. data/spec/fixtures/vcr/analytics_searchs_with_document_type.yml +57 -0
  36. data/spec/fixtures/vcr/analytics_top_no_result_queries.yml +57 -0
  37. data/spec/fixtures/vcr/analytics_top_no_result_queries_paginated.yml +57 -0
  38. data/spec/fixtures/vcr/analytics_top_queries.yml +57 -0
  39. data/spec/fixtures/vcr/analytics_top_queries_paginated.yml +57 -0
  40. data/spec/fixtures/vcr/analytics_top_queries_too_large.yml +53 -0
  41. data/spec/fixtures/vcr/async_create_or_update_document_failure.yml +48 -0
  42. data/spec/fixtures/vcr/async_create_or_update_document_success.yml +52 -0
  43. data/spec/fixtures/vcr/bulk_create_documents.yml +52 -0
  44. data/spec/fixtures/vcr/bulk_create_or_update_documents_failure.yml +47 -0
  45. data/spec/fixtures/vcr/bulk_create_or_update_documents_success.yml +52 -0
  46. data/spec/fixtures/vcr/bulk_create_or_update_documents_verbose_failure.yml +47 -0
  47. data/spec/fixtures/vcr/bulk_create_or_update_documents_verbose_success.yml +52 -0
  48. data/spec/fixtures/vcr/bulk_destroy_documents.yml +47 -0
  49. data/spec/fixtures/vcr/crawl_url.yml +47 -0
  50. data/spec/fixtures/vcr/create_document.yml +52 -0
  51. data/spec/fixtures/vcr/create_document_type.yml +47 -0
  52. data/spec/fixtures/vcr/create_domain.yml +47 -0
  53. data/spec/fixtures/vcr/create_engine.yml +47 -0
  54. data/spec/fixtures/vcr/create_or_update_document_create.yml +51 -0
  55. data/spec/fixtures/vcr/create_or_update_document_update.yml +51 -0
  56. data/spec/fixtures/vcr/create_user.yml +47 -0
  57. data/spec/fixtures/vcr/destroy_document.yml +43 -0
  58. data/spec/fixtures/vcr/destroy_document_type.yml +43 -0
  59. data/spec/fixtures/vcr/destroy_domain.yml +43 -0
  60. data/spec/fixtures/vcr/destroy_engine.yml +43 -0
  61. data/spec/fixtures/vcr/destroy_non_existent_document_type.yml +45 -0
  62. data/spec/fixtures/vcr/document_receipts_multiple.yml +48 -0
  63. data/spec/fixtures/vcr/document_receipts_multiple_complete.yml +48 -0
  64. data/spec/fixtures/vcr/document_type_search.yml +63 -0
  65. data/spec/fixtures/vcr/document_type_search_pagination.yml +47 -0
  66. data/spec/fixtures/vcr/document_type_suggest.yml +52 -0
  67. data/spec/fixtures/vcr/document_type_suggest_pagination.yml +47 -0
  68. data/spec/fixtures/vcr/engine_search.yml +67 -0
  69. data/spec/fixtures/vcr/engine_search_facets.yml +164 -0
  70. data/spec/fixtures/vcr/engine_search_pagination.yml +47 -0
  71. data/spec/fixtures/vcr/engine_suggest.yml +55 -0
  72. data/spec/fixtures/vcr/engine_suggest_pagination.yml +47 -0
  73. data/spec/fixtures/vcr/find_document.yml +50 -0
  74. data/spec/fixtures/vcr/find_document_type.yml +47 -0
  75. data/spec/fixtures/vcr/find_domain.yml +47 -0
  76. data/spec/fixtures/vcr/find_domain_failure.yml +45 -0
  77. data/spec/fixtures/vcr/find_engine.yml +47 -0
  78. data/spec/fixtures/vcr/list_document_type.yml +47 -0
  79. data/spec/fixtures/vcr/list_documents.yml +71 -0
  80. data/spec/fixtures/vcr/list_documents_with_pagination.yml +71 -0
  81. data/spec/fixtures/vcr/list_domains.yml +47 -0
  82. data/spec/fixtures/vcr/list_engines.yml +48 -0
  83. data/spec/fixtures/vcr/list_users.yml +47 -0
  84. data/spec/fixtures/vcr/list_users_with_pagination.yml +47 -0
  85. data/spec/fixtures/vcr/log_clickthrough_failure.yml +45 -0
  86. data/spec/fixtures/vcr/log_clickthrough_success.yml +47 -0
  87. data/spec/fixtures/vcr/recrawl_domain_failure.yml +46 -0
  88. data/spec/fixtures/vcr/recrawl_domain_success.yml +47 -0
  89. data/spec/fixtures/vcr/show_user.yml +47 -0
  90. data/spec/fixtures/vcr/update_document.yml +50 -0
  91. data/spec/fixtures/vcr/update_document_unknown_field_failure.yml +48 -0
  92. data/spec/fixtures/vcr/update_documents_failure_non_existent_document.yml +47 -0
  93. data/spec/fixtures/vcr/update_documents_success.yml +47 -0
  94. data/spec/fixtures/vcr/users_client_secret_incorrect.yml +44 -0
  95. data/spec/fixtures/vcr/users_no_api_key.yml +44 -0
  96. data/spec/fixtures/vcr/users_no_client_id_or_secret.yml +45 -0
  97. data/spec/platform_spec.rb +95 -0
  98. data/spec/spec_helper.rb +27 -0
  99. data/spec/ssl_spec.rb +34 -0
  100. data/spec/sso_spec.rb +24 -0
  101. metadata +279 -0
@@ -0,0 +1,9 @@
1
+ require 'elastic/site-search/client'
2
+ require 'elastic/site-search/sso'
3
+
4
+ module Elastic
5
+ module SiteSearch
6
+ extend Elastic::SiteSearch::Configuration
7
+ end
8
+ end
9
+
@@ -0,0 +1,527 @@
1
+ require 'elastic/site-search/configuration'
2
+ require 'elastic/site-search/result_set'
3
+ require 'elastic/site-search/request'
4
+
5
+ module Elastic
6
+ module SiteSearch
7
+ # API client for the {Elastic Site Search API}[https://www.elastic.co/products/site-search/service].
8
+ class Client
9
+ DEFAULT_TIMEOUT = 15
10
+
11
+ include Elastic::SiteSearch::Request
12
+
13
+ # Create a new Elastic::SiteSearch::Client client
14
+ #
15
+ # @param options [Hash] a hash of configuration options that will override what is set on the Elastic::SiteSearch class.
16
+ # @option options [String] :api_key an API Key to use for this client
17
+ # @option options [String] :platform_access_token a user's access token, will be used instead of API key for authenticating requests
18
+ # @option options [Numeric] :overall_timeout overall timeout for requests in seconds (default: 15s)
19
+ # @option options [Numeric] :open_timeout the number of seconds Net::HTTP (default: 15s)
20
+ # @option options [String] :proxy url of proxy to use, ex: "http://localhost:8888"
21
+ # will wait while opening a connection before raising a Timeout::Error
22
+
23
+ def initialize(options={})
24
+ @options = options
25
+ end
26
+
27
+ def api_key
28
+ @options[:api_key] || Elastic::SiteSearch.api_key
29
+ end
30
+
31
+ def platform_access_token
32
+ @options[:platform_access_token]
33
+ end
34
+
35
+ def proxy
36
+ @options[:proxy]
37
+ end
38
+
39
+ def open_timeout
40
+ @options[:open_timeout] || DEFAULT_TIMEOUT
41
+ end
42
+
43
+ def overall_timeout
44
+ (@options[:overall_timeout] || DEFAULT_TIMEOUT).to_f
45
+ end
46
+
47
+ def wrap(element)
48
+ [element].flatten(1)
49
+ end
50
+
51
+ # Methods wrapping the Elastic::SiteSearch private search and API endpoints. Using these methods, you can perform full-text
52
+ # and prefix searches over the Documents in your Engine, in a specific DocumentType, or any subset of DocumentTypes.
53
+ # You can also filter results and get faceted counts for results.
54
+ #
55
+ # For more information, visit the {REST API documentation on searching}[https://swiftype.com/documentation/site-search/searching].
56
+ module Search
57
+ # Perform an autocomplete (prefix) search over all the DocumentTypes of the provided engine.
58
+ # This can be used to implement type-ahead autocompletion. However, if your data is not sensitive,
59
+ # you should consider using the {Site Search public JSONP API}[https://swiftype.com/documentation/site-search/searching#public_search]
60
+ # in the user's web browser for suggest queries.
61
+ #
62
+ # results = client.suggest("site-search-api-example", "gla")
63
+ # results['videos'] # => [{'external_id' => 'v1uyQZNg2vE', 'title' => 'How It Feels [through Glass]', ...}, ...]
64
+ #
65
+ # @param [String] engine_id the Engine slug or ID
66
+ # @param [String] query the search terms
67
+ # @param [Hash] options search options (see {the REST API docs}[https://swiftype.com/documentation/site-search/searching] for a complete list)
68
+ # @option options [Integer] :page page number of results to fetch (server defaults to 1)
69
+ # @option options [Integer] :per_page number of results per page (server defaults to 20)
70
+ # @option options [Array] :document_types an array of DocumentType slugs to search.
71
+ # The server defaults to searching all DocumentTypes in the engine. To search a single document type,
72
+ # the +suggest_document_type+ method is more convenient.
73
+ # @option options [Hash] :fetch_fields a Hash of DocumentType slug to array of the fields to return with results
74
+ # (example: <code>{'videos' => ['title', 'channel_id']}</code>)
75
+ # @option options [Hash] :search_fields a Hash of DocumentType slug to array of the fields to search.
76
+ # May contain {field weight boosts}[https://swiftype.com/documentation/site-search/searching/field-weights]
77
+ # (example: <code>{'videos' => ['title^5', 'tags^2', 'caption']}</code>).
78
+ # The server defaults to searching all +string+ fields for suggest queries.
79
+ # @option options [Hash] :filters a Hash of DocumentType slug to filter definition Hash.
80
+ # See {filters in the REST API documentation}[https://swiftype.com/documentation/site-search/searching/filtering] for more details
81
+ # (example: <code>{'videos' => {'category_id' => ['23', '25']}}</code>)
82
+ # @option options [Hash] :functional_boosts a Hash of DocumentType slug to {functional boost}[https://swiftype.com/documentation/site-search/searching/boosting] definition
83
+ # (example: <code>{'videos' => {'view_count' => 'logarithmic'}}</code>).
84
+ # @option options [Hash] :sort_field a Hash of DocumentType slug to field name to sort on
85
+ # (example: <code>{'videos' => 'view_count'}</code>)
86
+ # @option options [Hash] :sort_direction a Hash of DocumentType slug to direction to sort
87
+ # (example: <code>'videos' => 'desc'</code>). Usually used with +:sort_field+.
88
+ #
89
+ # @return [Elastic::SiteSearch::ResultSet]
90
+ def suggest(engine_id, query, options={})
91
+ search_params = { :q => query }.merge(options)
92
+ response = post("engines/#{engine_id}/suggest.json", search_params)
93
+ ResultSet.new(response)
94
+ end
95
+
96
+ # Perform a full-text search over all the DocumentTypes of the provided engine.
97
+ #
98
+ # results = client.search("site-search-api-example", "glass")
99
+ # results['videos'] # => [{'external_id' => 'v1uyQZNg2vE', 'title' => 'How It Feels [through Glass]', ...}, ...]
100
+ #
101
+ # @param [String] engine_id the Engine slug or ID
102
+ # @param [String] query the search terms (may be nil)
103
+ # @param [Hash] options search options (see {the REST API docs}[https://swiftype.com/documentation/site-search/searching] for a complete list)
104
+ # @option options [Integer] :page page number of results to fetch (server defaults to 1)
105
+ # @option options [Integer] :per_page number of results per page (server defaults to 20)
106
+ # @option options [Array] :document_types an array of DocumentType slugs to search.
107
+ # The server defaults to searching all DocumentTypes in the engine. To search a single document type,
108
+ # the +search_document_type+ method is more convenient.
109
+ # @option options [Hash] :fetch_fields a Hash of DocumentType slug to array of the fields to return with results
110
+ # (example: <code>{'videos' => ['title', 'channel_id']}</code>)
111
+ # @option options [Hash] :search_fields a Hash of DocumentType slug to array of the fields to search.
112
+ # May contain {field weight boosts}[https://swiftype.com/documentation/site-search/searching/field-weights]
113
+ # (example: <code>{'videos' => ['title^5', 'tags^2', 'caption']}</code>).
114
+ # The server defaults to searching all +string+ and +text+ fields for search queries.
115
+ # @option options [Hash] :filters a Hash of DocumentType slug to filter definition Hash.
116
+ # See {filters in the REST API documentation}[https://swiftype.com/documentation/site-search/searching/filtering] for more details
117
+ # (example: <code>{'videos' => {'category_id' => ['23', '25']}}</code>)
118
+ # @option options [Hash] :functional_boosts a Hash of DocumentType slug to {functional boost}[https://swiftype.com/documentation/site-search/searching/boosting] definition
119
+ # (example: <code>{'videos' => {'view_count' => 'logarithmic'}}</code>).
120
+ # @option options [Hash] :facets a Hash of DocumentType slug to an Array of field names to provide facetted counts for
121
+ # (example: <code>{'videos' => ['category_id', 'channel_id']}</code>)
122
+ # @option options [Hash] :sort_field a Hash of DocumentType slug to field name to sort on
123
+ # (example: <code>{'videos' => 'view_count'}</code>)
124
+ # @option options [Hash] :sort_direction a Hash of DocumentType slug to direction to sort
125
+ # (example: <code>'videos' => 'desc'</code>). Usually used with +:sort_field+.
126
+ #
127
+ # @return [Elastic::SiteSearch::ResultSet]
128
+ def search(engine_id, query, options={})
129
+ search_params = { :q => query }.merge(options)
130
+ response = post("engines/#{engine_id}/search.json", search_params)
131
+ ResultSet.new(response)
132
+ end
133
+
134
+ # Perform an autocomplete (prefix) search over a single DocumentType in an Engine.
135
+ # This can be used to implement type-ahead autocompletion. However, if your data is not sensitive,
136
+ # you should consider using the {Site Search public JSONP API}[https://swiftype.com/documentation/site-search/searching#public_search]
137
+ # in the user's web browser for suggest queries.
138
+ #
139
+ # results = client.suggest_document_type("site-search-api-example", "videos", "gla")
140
+ # results['videos'] # => [{'external_id' => 'v1uyQZNg2vE', 'title' => 'How It Feels [through Glass]', ...}, ...]
141
+ #
142
+ # @param [String] engine_id the Engine slug or ID
143
+ # @param [String] query the search terms
144
+ # @param [Hash] options search options (see {the REST API docs}[https://swiftype.com/documentation/site-search/searching] for a complete list)
145
+ # @option options [Integer] :page page number of results to fetch (server defaults to 1)
146
+ # @option options [Integer] :per_page number of results per page (server defaults to 20)
147
+ # @option options [Array] :document_types an array of DocumentType slugs to search.
148
+ # The server defaults to searching all DocumentTypes in the engine. To search a single document type,
149
+ # the +suggest_document_type+ method is more convenient.
150
+ # @option options [Hash] :fetch_fields a Hash of DocumentType slug to array of the fields to return with results
151
+ # (example: <code>{'videos' => ['title', 'channel_id']}</code>)
152
+ # @option options [Hash] :search_fields a Hash of DocumentType slug to array of the fields to search.
153
+ # May contain {field weight boosts}[https://swiftype.com/documentation/site-search/searching/field-weights]
154
+ # (example: <code>{'videos' => ['title^5', 'tags^2', 'caption']}</code>).
155
+ # The server defaults to searching all +string+ fields for suggest queries.
156
+ # @option options [Hash] :filters a Hash of DocumentType slug to filter definition Hash.
157
+ # See {filters in the REST API documentation}[https://swiftype.com/documentation/site-search/searching/filtering] for more details
158
+ # (example: <code>{'videos' => {'category_id' => ['23', '25']}}</code>)
159
+ # @option options [Hash] :functional_boosts a Hash of DocumentType slug to {functional boost}[https://swiftype.com/documentation/site-search/searching/boosting] definition
160
+ # (example: <code>{'videos' => {'view_count' => 'logarithmic'}}</code>).
161
+ # @option options [Hash] :sort_field a Hash of DocumentType slug to field name to sort on
162
+ # (example: <code>{'videos' => 'view_count'}</code>)
163
+ # @option options [Hash] :sort_direction a Hash of DocumentType slug to direction to sort
164
+ # (example: <code>'videos' => 'desc'</code>). Usually used with +:sort_field+.
165
+ #
166
+ # @return [Elastic::SiteSearch::ResultSet]
167
+ def suggest_document_type(engine_id, document_type_id, query, options={})
168
+ search_params = { :q => query }.merge(options)
169
+ response = post("engines/#{engine_id}/document_types/#{document_type_id}/suggest.json", search_params)
170
+ ResultSet.new(response)
171
+ end
172
+
173
+ # Perform a full-text search over a single DocumentType in an Engine.
174
+ #
175
+ # results = client.search_document_type("site-search-api-example", "videos", "glass")
176
+ # results['videos'] # => [{'external_id' => 'v1uyQZNg2vE', 'title' => 'How It Feels [through Glass]', ...}, ...]
177
+ #
178
+ # @param [String] engine_id the Engine slug or ID
179
+ # @param [String] document_type_id the DocumentType slug or ID
180
+ # @param [String] query the search terms (may be nil)
181
+ # @param [Hash] options search options (see {the REST API docs}[https://swiftype.com/documentation/site-search/searching] for a complete list)
182
+ # @option options [Integer] :page page number of results to fetch (server defaults to 1)
183
+ # @option options [Integer] :per_page number of results per page (server defaults to 20)
184
+ # @option options [Hash] :fetch_fields a Hash of DocumentType slug to array of the fields to return with results
185
+ # (example: <code>{'videos' => ['title', 'channel_id']}</code>)
186
+ # @option options [Hash] :search_fields a Hash of DocumentType slug to array of the fields to search.
187
+ # May contain {field weight boosts}[https://swiftype.com/documentation/site-search/searching/field-weights]
188
+ # (example: <code>{'videos' => ['title^5', 'tags^2', 'caption']}</code>).
189
+ # The server defaults to searching all +string+ and +text+ fields for search queries.
190
+ # @option options [Hash] :filters a Hash of DocumentType slug to filter definition Hash.
191
+ # See {filters in the REST API documentation}[https://swiftype.com/documentation/site-search/searching/filtering] for more details
192
+ # (example: <code>{'videos' => {'category_id' => ['23', '25']}}</code>)
193
+ # @option options [Hash] :functional_boosts a Hash of DocumentType slug to {functional boost}[https://swiftype.com/documentation/site-search/searching/boosting] definition
194
+ # (example: <code>{'videos' => {'view_count' => 'logarithmic'}}</code>).
195
+ # @option options [Hash] :facets a Hash of DocumentType slug to an Array of field names to provide facetted counts for
196
+ # (example: <code>{'videos' => ['category_id', 'channel_id']}</code>)
197
+ # @option options [Hash] :sort_field a Hash of DocumentType slug to field name to sort on
198
+ # (example: <code>{'videos' => 'view_count'}</code>)
199
+ # @option options [Hash] :sort_direction a Hash of DocumentType slug to direction to sort
200
+ # (example: <code>'videos' => 'desc'</code>). Usually used with +:sort_field+.
201
+ #
202
+ # @return [Elastic::SiteSearch::ResultSet]
203
+ def search_document_type(engine_id, document_type_id, query, options={})
204
+ search_params = { :q => query }.merge(options)
205
+ response = post("engines/#{engine_id}/document_types/#{document_type_id}/search.json", search_params)
206
+ ResultSet.new(response)
207
+ end
208
+ end
209
+
210
+ module User
211
+ # List users for the configured application.
212
+ #
213
+ # @param options [Hash]
214
+ # @option options [Integer] :page page number of users to fetch (server defaults to 1)
215
+ # @option options [Integer] :per_page users to return per page (server defaults to 50)
216
+ def users(options={})
217
+ params = {
218
+ :client_id => Elastic::SiteSearch.platform_client_id,
219
+ :client_secret => Elastic::SiteSearch.platform_client_secret
220
+ }
221
+ get("users.json", params.merge(options))
222
+ end
223
+
224
+ # Create a new user for the configured application.
225
+ def create_user
226
+ params = {
227
+ :client_id => Elastic::SiteSearch.platform_client_id,
228
+ :client_secret => Elastic::SiteSearch.platform_client_secret
229
+ }
230
+ post("users.json", params)
231
+ end
232
+
233
+ # Return a user created by the configured application.
234
+ #
235
+ # @param user_id [String] the Site Search User ID
236
+ def user(user_id)
237
+ params = {
238
+ :client_id => Elastic::SiteSearch.platform_client_id,
239
+ :client_secret => Elastic::SiteSearch.platform_client_secret
240
+ }
241
+ get("users/#{user_id}.json", params)
242
+ end
243
+ end
244
+
245
+ # An Engine is a search engine that lets you search and filter the Documents it contains.
246
+ # For more information, see the {REST API overview}[https://swiftype.com/documentation/site-search/overview].
247
+ module Engine
248
+ def engines
249
+ get("engines.json")
250
+ end
251
+
252
+ def engine(engine_id)
253
+ get("engines/#{engine_id}.json")
254
+ end
255
+
256
+ def create_engine(name)
257
+ post("engines.json", :engine => {:name => name})
258
+ end
259
+
260
+ def destroy_engine(engine_id)
261
+ delete("engines/#{engine_id}.json")
262
+ end
263
+ end
264
+
265
+ # Every Document must belong to a DocumentType. For more information, see the {REST API overview}[https://swiftype.com/documentation/site-search/overview].
266
+ module DocumentType
267
+ def document_types(engine_id)
268
+ get("engines/#{engine_id}/document_types.json")
269
+ end
270
+
271
+ def document_type(engine_id, document_type_id)
272
+ get("engines/#{engine_id}/document_types/#{document_type_id}.json")
273
+ end
274
+
275
+ def create_document_type(engine_id, name)
276
+ post("engines/#{engine_id}/document_types.json", :document_type => {:name => name})
277
+ end
278
+
279
+ def destroy_document_type(engine_id, document_type_id)
280
+ delete("engines/#{engine_id}/document_types/#{document_type_id}.json")
281
+ end
282
+ end
283
+
284
+ # Documents have fields that can be searched or filtered.
285
+ #
286
+ # For more information on indexing documents, see the {REST API indexing documentation}[https://swiftype.com/documentation/site-search/indexing].
287
+ module Document
288
+ def documents(engine_id, document_type_id, page=nil, per_page=nil)
289
+ options = {}
290
+ options[:page] = page if page
291
+ options[:per_page] = per_page if per_page
292
+ get("engines/#{engine_id}/document_types/#{document_type_id}/documents.json", options)
293
+ end
294
+
295
+ def document(engine_id, document_type_id, document_id)
296
+ get("engines/#{engine_id}/document_types/#{document_type_id}/documents/#{document_id}.json")
297
+ end
298
+
299
+ def create_document(engine_id, document_type_id, document={})
300
+ post("engines/#{engine_id}/document_types/#{document_type_id}/documents.json", :document => document)
301
+ end
302
+
303
+ def create_documents(engine_id, document_type_id, documents=[])
304
+ post("engines/#{engine_id}/document_types/#{document_type_id}/documents/bulk_create.json", :documents => documents)
305
+ end
306
+
307
+ def destroy_document(engine_id, document_type_id, document_id)
308
+ delete("engines/#{engine_id}/document_types/#{document_type_id}/documents/#{document_id}.json")
309
+ end
310
+
311
+ def destroy_documents(engine_id, document_type_id, document_ids=[])
312
+ post("engines/#{engine_id}/document_types/#{document_type_id}/documents/bulk_destroy.json", :documents => document_ids)
313
+ end
314
+
315
+ def create_or_update_document(engine_id, document_type_id, document={})
316
+ post("engines/#{engine_id}/document_types/#{document_type_id}/documents/create_or_update.json", :document => document)
317
+ end
318
+
319
+ def create_or_update_documents(engine_id, document_type_id, documents=[])
320
+ post("engines/#{engine_id}/document_types/#{document_type_id}/documents/bulk_create_or_update.json", :documents => documents)
321
+ end
322
+
323
+ def create_or_update_documents_verbose(engine_id, document_type_id, documents=[])
324
+ post("engines/#{engine_id}/document_types/#{document_type_id}/documents/bulk_create_or_update_verbose.json", :documents => documents)
325
+ end
326
+
327
+ def update_document(engine_id, document_type_id, document_id, fields)
328
+ put("engines/#{engine_id}/document_types/#{document_type_id}/documents/#{document_id}/update_fields.json", { :fields => fields })
329
+ end
330
+
331
+ def update_documents(engine_id, document_type_id, documents={})
332
+ put("engines/#{engine_id}/document_types/#{document_type_id}/documents/bulk_update.json", { :documents => documents })
333
+ end
334
+
335
+ def async_create_or_update_documents(engine_id, document_type_id, documents=[])
336
+ post("engines/#{engine_id}/document_types/#{document_type_id}/documents/async_bulk_create_or_update.json", :documents => documents)
337
+ end
338
+
339
+ # Retrieve Document Receipts from the API by ID
340
+ #
341
+ # @param [Array<String>] receipt_ids an Array of Document Receipt IDs
342
+ #
343
+ # @return [Array<Hash>] an Array of Document Receipt hashes
344
+ def document_receipts(receipt_ids)
345
+ post("document_receipts.json", :ids => receipt_ids)
346
+ end
347
+
348
+ # Index a batch of documents using the {asynchronous API}[https://swiftype.com/documentation/site-search/indexing#asynchronous].
349
+ # This is a good choice if you have a large number of documents.
350
+ #
351
+ # @param [String] engine_id the Engine slug or ID
352
+ # @param [String] document_type_id the Document Type slug or ID
353
+ # @param [Array] documents an Array of Document Hashes
354
+ # @param [Hash] options additional options
355
+ # @option options [Boolean] :async (false) When true, output is document receipts created. When false, poll until all receipts are no longer pending or timeout is reached.
356
+ # @option options [Numeric] :timeout (10) Number of seconds to wait before raising an exception
357
+ #
358
+ # @return [Array<Hash>] an Array of newly-created Document Receipt hashes if used in :async => true mode
359
+ # @return [Array<Hash>] an Array of processed Document Receipt hashes if used in :async => false mode
360
+ #
361
+ # @raise [Timeout::Error] when used in :async => false mode and the timeout expires
362
+ def index_documents(engine_id, document_type_id, documents = [], options = {})
363
+ documents = wrap(documents)
364
+
365
+ res = async_create_or_update_documents(engine_id, document_type_id, documents)
366
+
367
+ if options[:async]
368
+ res
369
+ else
370
+ receipt_ids = res["document_receipts"].map { |a| a["id"] }
371
+
372
+ poll(options) do
373
+ receipts = document_receipts(receipt_ids)
374
+ flag = receipts.all? { |a| a["status"] != "pending" }
375
+ flag ? receipts : false
376
+ end
377
+ end
378
+ end
379
+ end
380
+
381
+ # The analytics API provides a way to export analytics data similar to what is found in the Site Search Dashboard.
382
+ # See the {REST API Documentation}[https://swiftype.com/documentation/site-search/analytics] for details.
383
+ module Analytics
384
+ # Return the number of searches that occurred on each day in the time range for the provided Engine and optional DocumentType.
385
+ # The maximum time range between start and end dates is 30 days.
386
+ #
387
+ # @param [String] engine_id the Engine slug or ID
388
+ # @param [Hash] options
389
+ # @option options [String] :document_type_id the DocumentType slug or ID
390
+ # @option options [String] :start_date a date formatted like '2013-01-01'
391
+ # @option options [String] :end_date to a date formatted like '2013-01-01'
392
+ def analytics_searches(engine_id, options={})
393
+ document_type_id = options.delete(:document_type_id)
394
+ if document_type_id
395
+ get("engines/#{engine_id}/document_types/#{document_type_id}/analytics/searches.json", options)
396
+ else
397
+ get("engines/#{engine_id}/analytics/searches.json", options)
398
+ end
399
+ end
400
+
401
+ # Return the number of autoselects (when a user clicks a result from an autocomplete dropdown)
402
+ # that occurred on each day in the time range for the provided Engine and optional DocumentType.
403
+ # The maximum time range between start and end dates is 30 days.
404
+ #
405
+ # @param [String] engine_id the Engine slug or ID
406
+ # @param [Hash] options
407
+ # @option options [String] :document_type_id the DocumentType slug or ID
408
+ # @option options [String] :start_date a date formatted like '2013-01-01'
409
+ # @option options [String] :end_date to a date formatted like '2013-01-01'
410
+ def analytics_autoselects(engine_id, options={})
411
+ document_type_id = options.delete(:document_type_id)
412
+ if document_type_id
413
+ get("engines/#{engine_id}/document_types/#{document_type_id}/analytics/autoselects.json", options)
414
+ else
415
+ get("engines/#{engine_id}/analytics/autoselects.json", options)
416
+ end
417
+ end
418
+
419
+ # Return the number of clickthroughs (when a user clicks a result from a search results page)
420
+ # that occurred on each day in the time range for the provided Engine and optional DocumentType.
421
+ # The maximum time range between start and end dates is 30 days.
422
+ #
423
+ # @param [String] engine_id the Engine slug or ID
424
+ # @param [Hash] options
425
+ # @option options [String] :document_type_id the DocumentType slug or ID
426
+ # @option options [String] :start_date a date formatted like '2013-01-01'
427
+ # @option options [String] :end_date to a date formatted like '2013-01-01'
428
+ def analytics_clicks(engine_id, options={})
429
+ document_type_id = options.delete(:document_type_id)
430
+ if document_type_id
431
+ get("engines/#{engine_id}/document_types/#{document_type_id}/analytics/clicks.json", options)
432
+ else
433
+ get("engines/#{engine_id}/analytics/clicks.json", options)
434
+ end
435
+ end
436
+
437
+ # Return top queries for an engine.
438
+ #
439
+ # @param [String] engine_id the engine slug or ID
440
+ # @param [Hash] options
441
+ # @option options [String] :start_date a date formatted like '2013-01-01'
442
+ # @option options [String] :end_date a date formatted like '2013-01-01'
443
+ # @option options [Integer] :page page number. The server defaults to page 1 and the maximum is 50.
444
+ # @option options [Integer] :per_page number of results per page. The server defaults to 20 and the maximum is 100.
445
+ def analytics_top_queries(engine_id, options={})
446
+ get("engines/#{engine_id}/analytics/top_queries.json", options)
447
+ end
448
+
449
+ # Return top queries with no results for an engine.
450
+ #
451
+ # @param [String] engine_id the engine slug or ID
452
+ # @param [Hash] options
453
+ # @option options [String] :start_date a date formatted like '2013-01-01'
454
+ # @option options [String] :end_date a date formatted like '2013-01-01'
455
+ # @option options [Integer] :page page number. The server defaults to page 1 and the maximum is 50.
456
+ # @option options [Integer] :per_page number of results per page. The server defaults to 20 and the maximum is 100.
457
+ def analytics_top_no_result_queries(engine_id, options={})
458
+ get("engines/#{engine_id}/analytics/top_no_result_queries.json", options)
459
+ end
460
+ end
461
+
462
+ # A Domain represents a host in a crawler-based Engine. Domains
463
+ # are only relevant to crawler-base engines, but you can
464
+ # manipulate them through the REST API.
465
+ module Domain
466
+ def domains(engine_id)
467
+ get("engines/#{engine_id}/domains.json")
468
+ end
469
+
470
+ def domain(engine_id, domain_id)
471
+ get("engines/#{engine_id}/domains/#{domain_id}.json")
472
+ end
473
+
474
+ def create_domain(engine_id, url)
475
+ post("engines/#{engine_id}/domains.json", {:domain => {:submitted_url => url}})
476
+ end
477
+
478
+ def destroy_domain(engine_id, domain_id)
479
+ delete("engines/#{engine_id}/domains/#{domain_id}.json")
480
+ end
481
+
482
+ # Trigger a recrawl request for a Domain. Note that this will fail if you have exceeded your recrawl limit.
483
+ def recrawl_domain(engine_id, domain_id)
484
+ put("engines/#{engine_id}/domains/#{domain_id}/recrawl.json")
485
+ end
486
+
487
+ # Request to add or update a URL on a Domain. The host of the URL must match the host of the Domain.
488
+ #
489
+ # @param [String] engine_id the Engine slug or ID
490
+ # @param [String] domain_id the Domain ID
491
+ # @param [String] url the URL to crawl
492
+ def crawl_url(engine_id, domain_id, url)
493
+ put("engines/#{engine_id}/domains/#{domain_id}/crawl_url.json", {:url => url})
494
+ end
495
+ end
496
+
497
+ # A Clickthrough represents a user clicking on a full-text search result.
498
+ #
499
+ # If you are routing searches through your own server instead of
500
+ # executing them client-side with the Site Search JavaScript API, you
501
+ # will need to record clickthroughs yourself.
502
+ module Clickthrough
503
+ # Log a clickthrough for a Document.
504
+ #
505
+ # @param [String] engine_id the Engine slug or ID
506
+ # @param [String] document_type the DocumentType slug or ID
507
+ # @param [String] q the query that generated the search result
508
+ # @param [String] id the external_id or ID of the Document
509
+ def log_clickthrough(engine_id, document_type, q, id)
510
+ post(
511
+ "engines/#{engine_id}/document_types/#{document_type}/analytics/log_clickthrough.json",
512
+ {:q => q, :id => id}
513
+ )
514
+ end
515
+ end
516
+
517
+ include Elastic::SiteSearch::Client::User
518
+ include Elastic::SiteSearch::Client::Search
519
+ include Elastic::SiteSearch::Client::Engine
520
+ include Elastic::SiteSearch::Client::DocumentType
521
+ include Elastic::SiteSearch::Client::Document
522
+ include Elastic::SiteSearch::Client::Analytics
523
+ include Elastic::SiteSearch::Client::Domain
524
+ include Elastic::SiteSearch::Client::Clickthrough
525
+ end
526
+ end
527
+ end