swiftype 0.0.5 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/.gitignore +5 -0
  2. data/.travis.yml +6 -0
  3. data/Gemfile +1 -1
  4. data/README.md +202 -283
  5. data/lib/data/ca-bundle.crt +3554 -0
  6. data/lib/swiftype.rb +7 -31
  7. data/lib/swiftype/client.rb +439 -11
  8. data/lib/swiftype/configuration.rb +29 -4
  9. data/lib/swiftype/exceptions.rb +2 -0
  10. data/lib/swiftype/ext/backport-uri.rb +33 -0
  11. data/lib/swiftype/request.rb +88 -20
  12. data/lib/swiftype/result_set.rb +43 -6
  13. data/lib/swiftype/sso.rb +20 -0
  14. data/lib/swiftype/version.rb +1 -1
  15. data/spec/client_spec.rb +576 -0
  16. data/spec/configuration_spec.rb +36 -0
  17. data/spec/deprecated_spec.rb +20 -0
  18. data/spec/fixtures/vcr/analytics_autoselects.yml +55 -0
  19. data/spec/fixtures/vcr/analytics_autoselects_with_document_type.yml +55 -0
  20. data/spec/fixtures/vcr/analytics_autoselects_with_document_type_and_time_range.yml +55 -0
  21. data/spec/fixtures/vcr/analytics_autoselects_with_time_range.yml +55 -0
  22. data/spec/fixtures/vcr/analytics_clicks.yml +55 -0
  23. data/spec/fixtures/vcr/analytics_clicks_with_document_type.yml +55 -0
  24. data/spec/fixtures/vcr/analytics_clicks_with_document_type_and_time_range.yml +55 -0
  25. data/spec/fixtures/vcr/analytics_clicks_with_time_range.yml +55 -0
  26. data/spec/fixtures/vcr/analytics_searches.yml +55 -0
  27. data/spec/fixtures/vcr/analytics_searches_with_document_type_and_time_range.yml +55 -0
  28. data/spec/fixtures/vcr/analytics_searches_with_time_range.yml +55 -0
  29. data/spec/fixtures/vcr/analytics_searchs_with_document_type.yml +55 -0
  30. data/spec/fixtures/vcr/analytics_top_no_result_queries.yml +55 -0
  31. data/spec/fixtures/vcr/analytics_top_no_result_queries_paginated.yml +55 -0
  32. data/spec/fixtures/vcr/analytics_top_queries.yml +55 -0
  33. data/spec/fixtures/vcr/analytics_top_queries_paginated.yml +55 -0
  34. data/spec/fixtures/vcr/analytics_top_queries_too_large.yml +51 -0
  35. data/spec/fixtures/vcr/bulk_create_documents.yml +49 -0
  36. data/spec/fixtures/vcr/bulk_create_or_update_documents_failure.yml +45 -0
  37. data/spec/fixtures/vcr/bulk_create_or_update_documents_success.yml +49 -0
  38. data/spec/fixtures/vcr/bulk_destroy_documents.yml +45 -0
  39. data/spec/fixtures/vcr/crawl_url.yml +45 -0
  40. data/spec/fixtures/vcr/create_document.yml +48 -0
  41. data/spec/fixtures/vcr/create_document_type.yml +45 -0
  42. data/spec/fixtures/vcr/create_domain.yml +45 -0
  43. data/spec/fixtures/vcr/create_engine.yml +45 -0
  44. data/spec/fixtures/vcr/create_or_update_document_create.yml +47 -0
  45. data/spec/fixtures/vcr/create_or_update_document_update.yml +47 -0
  46. data/spec/fixtures/vcr/create_user.yml +45 -0
  47. data/spec/fixtures/vcr/destroy_document.yml +41 -0
  48. data/spec/fixtures/vcr/destroy_document_type.yml +41 -0
  49. data/spec/fixtures/vcr/destroy_domain.yml +41 -0
  50. data/spec/fixtures/vcr/destroy_engine.yml +41 -0
  51. data/spec/fixtures/vcr/destroy_non_existent_document_type.yml +43 -0
  52. data/spec/fixtures/vcr/document_type_search.yml +60 -0
  53. data/spec/fixtures/vcr/document_type_search_pagination.yml +45 -0
  54. data/spec/fixtures/vcr/document_type_suggest.yml +50 -0
  55. data/spec/fixtures/vcr/document_type_suggest_pagination.yml +45 -0
  56. data/spec/fixtures/vcr/engine_search.yml +64 -0
  57. data/spec/fixtures/vcr/engine_search_facets.yml +162 -0
  58. data/spec/fixtures/vcr/engine_search_pagination.yml +45 -0
  59. data/spec/fixtures/vcr/engine_suggest.yml +52 -0
  60. data/spec/fixtures/vcr/engine_suggest_pagination.yml +45 -0
  61. data/spec/fixtures/vcr/find_document.yml +47 -0
  62. data/spec/fixtures/vcr/find_document_type.yml +45 -0
  63. data/spec/fixtures/vcr/find_domain.yml +45 -0
  64. data/spec/fixtures/vcr/find_domain_failure.yml +43 -0
  65. data/spec/fixtures/vcr/find_engine.yml +45 -0
  66. data/spec/fixtures/vcr/list_document_type.yml +45 -0
  67. data/spec/fixtures/vcr/list_documents.yml +68 -0
  68. data/spec/fixtures/vcr/list_documents_with_pagination.yml +68 -0
  69. data/spec/fixtures/vcr/list_domains.yml +45 -0
  70. data/spec/fixtures/vcr/list_engines.yml +46 -0
  71. data/spec/fixtures/vcr/list_users.yml +45 -0
  72. data/spec/fixtures/vcr/list_users_with_pagination.yml +45 -0
  73. data/spec/fixtures/vcr/log_clickthrough_failure.yml +43 -0
  74. data/spec/fixtures/vcr/log_clickthrough_success.yml +45 -0
  75. data/spec/fixtures/vcr/recrawl_domain_failure.yml +44 -0
  76. data/spec/fixtures/vcr/recrawl_domain_success.yml +45 -0
  77. data/spec/fixtures/vcr/show_user.yml +45 -0
  78. data/spec/fixtures/vcr/update_document.yml +47 -0
  79. data/spec/fixtures/vcr/update_document_unknown_field_failure.yml +45 -0
  80. data/spec/fixtures/vcr/update_documents_failure_non_existent_document.yml +45 -0
  81. data/spec/fixtures/vcr/update_documents_success.yml +45 -0
  82. data/spec/fixtures/vcr/users_client_secret_incorrect.yml +42 -0
  83. data/spec/fixtures/vcr/users_no_api_key.yml +42 -0
  84. data/spec/fixtures/vcr/users_no_client_id_or_secret.yml +43 -0
  85. data/spec/platform_spec.rb +95 -0
  86. data/spec/spec_helper.rb +26 -0
  87. data/spec/ssl_spec.rb +34 -0
  88. data/spec/sso_spec.rb +24 -0
  89. data/swiftype.gemspec +10 -11
  90. metadata +183 -52
  91. data/lib/swiftype/base_model.rb +0 -89
  92. data/lib/swiftype/connection.rb +0 -47
  93. data/lib/swiftype/document.rb +0 -17
  94. data/lib/swiftype/document_type.rb +0 -69
  95. data/lib/swiftype/easy.rb +0 -77
  96. data/lib/swiftype/engine.rb +0 -33
  97. data/lib/swiftype/search.rb +0 -23
data/.gitignore CHANGED
@@ -3,3 +3,8 @@
3
3
  Gemfile.lock
4
4
  pkg/*
5
5
  .DS_Store
6
+ .rvmrc
7
+ .ruby-version
8
+ .ruby-gemset
9
+ .yardoc
10
+ doc
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ script: rspec spec/platform_spec.rb
3
+ rvm:
4
+ - 1.8.7
5
+ - 1.9.3
6
+ - 2.0.0
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source "http://rubygems.org"
1
+ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in swiftype-rb.gemspec
4
4
  gemspec
data/README.md CHANGED
@@ -1,419 +1,338 @@
1
- Swiftype Ruby Client (beta)
2
- ===
1
+ # Swiftype Ruby API Client
3
2
 
4
- The official [Swiftype](http://swiftype.com) Ruby client for communicating with the Swiftype API. Learn more about Swiftype by visiting [swiftype.com](http://swiftype.com) and creating an account.
3
+ [![Build Status](https://travis-ci.org/swiftype/swiftype-rb.png?branch=easy)](https://travis-ci.org/swiftype/swiftype-rb)
5
4
 
5
+ This is a simple client for the [Swiftype API](https://swiftype.com/documentation/overview) with no dependencies outside core Ruby (for 1.9 and 2.0; Ruby 1.8 requires the JSON gem).
6
6
 
7
- Prerequisites
8
- ---
9
- 1. A Swiftype account. Sign up at [swiftype.com](http://swiftype.com).
10
- 2. A compatible Ruby environment.
7
+ ## Getting Started
11
8
 
9
+ Before beginning with the Swiftype gem, you should be familar with the concepts behind the Swiftype API: **Engines**, **DocumentTypes**, and **Documents**.
12
10
 
13
- Installation
14
- ---
11
+ An **Engine** is a search engine. It can contain one or more **DocumentTypes** which are collections of **Documents**. A **Document** is a collection of fields that can be queried using the Swiftype API. Documents have a special **external_id** field that ties a Document in Swiftype to a record in your system. The layout of fields of the Documents belonging to a DocumentType is called a **schema**. Fields may be strings, integers, geographic locations, and so forth.
15
12
 
16
- To install the gem, execute:
17
-
18
- gem install swiftype
19
-
20
- Or place `gem 'swiftype'` in your `Gemfile` and run `bundle install`.
21
-
22
- To use the GitHub version, you may add this to your Gemfile:
13
+ The Documents in your Engine can be searched two ways: **full-text** (`search`) or **autocomplete** (`suggest`). The difference is that autocomplete queries work on prefixes (for example, "gla" will match "glass"). This is less accurage in general, but is useful for implementing type-ahead search drop downs.
23
14
 
24
- gem 'swiftype', :git => "https://github.com/swiftype/swiftype-rb.git"
15
+ You can think of an Engine as a database, DocumentTypes as tables, and Documents as rows. Using the API, you can search an engine for all Documents containing a word. You can also search an individual DocumentType, or any subset of DocumentTypes.
25
16
 
26
- Overview
27
- ---
17
+ The examples in this documentation use the schema defined in the [swiftype-api-example](https://github.com/swiftype/swiftype-api-example) project, which is based on YouTube. It has two DocumentTypes, **videos** and **channels**. Using the script found in the swiftype-api-example project, you can create your own search engine that matches the examples and try the queries for yourself.
28
18
 
29
- The client has a few basic methods on `Swiftype` for dealing with `Engines`. Beyond that, you can perform standard (CRUD) operations on any of the resources.
19
+ To learn more about the Swiftype API, read the [API overview](https://swiftype.com/documentation/overview) and our [schema design tutorial](https://swiftype.com/documentation/tutorials/schema_design).
30
20
 
31
- ### Resources
21
+ ## Installation
32
22
 
33
- #### Engine
23
+ To install the gem, execute:
34
24
 
35
- `Engines` are the top-level objects in Swiftype. They have a free-form `name` field that is translated into a `slug` identifier.
25
+ gem install swiftype
36
26
 
37
- #### Document Type
27
+ Or place `gem 'swiftype', '~> 1.0.0` in your `Gemfile` and run `bundle install`.
38
28
 
39
- `DocumentTypes` specify the structure of a set of documents in the `Engine` and are the entry point for searches. There are three types of fields on a `DocumentType`: `:string`, `:text`, `:enum`, `:integer`, `:float`, and `:date`.
29
+ ## Usage
40
30
 
41
- `:string` is for short strings that can be matched in both prefix and full-text searches. _Example: Chapter titles in a book._
31
+ ### Configuration:
42
32
 
43
- `:text` can be long strings. They are meant for full-text searches only and will not be used for prefix queries. _Example: Entire text of an essay._
33
+ Before issuing commands to the API, configure the client with your API key:
44
34
 
45
- `:enum` are string traits of a document. They are not analyzed in any way, and thus can be used to filter and sort queries. _Example: Hardcover or paperback._
35
+ Swiftype.api_key = 'YOUR_API_KEY'
46
36
 
47
- `:date` are ISO 8601 compatible time strings. They can also be used to filter and sort queries.
37
+ You can find your API key in your [Account Settings](https://swiftype.com/settings/account).
48
38
 
39
+ ### Create a client
49
40
 
41
+ client = Swiftype::Client.new
50
42
 
51
- #### Document
43
+ You can also provide the API key when creating the client instance:
52
44
 
53
- `Documents` represent all of the pieces of content in an `Engine`. They are children of a `DocumentType` and conform to its field specification (note: you do *not* need to specify the fields ahead of time, they will be inferred by the contents of a document). When you perform a search on a `DocumentType`, you will receive `Document` results. `external_id` is the only required field for a `Document`. It can be any value, such as a numeric ID.
45
+ client = Swiftype::Client.new(:api_key => 'different_api_key')
54
46
 
47
+ If the API key is provided as an option to constructor, it will override the globally configured Swiftype API key (if any).
55
48
 
49
+ ### Full-text search
56
50
 
57
- Basic Usage
58
- ===
51
+ If you want to search for `cat` on your engine, you can use:
59
52
 
60
- Configuration:
61
- ---
53
+ results = client.search('swiftype-api-example', 'cat')
54
+ results['videos'] # => [{'external_id' => 'QH2-TGUlwu4', 'title' => 'Nyan Cat [original]', ... }, ... ]
55
+ results['channels'] # => [{'external_id' => 'UC3VHfy8e1jbDnT5TG2pjP1w', 'title' => 'saraj00n', ... }, ... ]
62
56
 
63
- Before issuing commands to the API, configure the client with your API key:
57
+ To limit the search to only the `videos` DocumentType:
64
58
 
65
- ```ruby
66
- Swiftype.configure do |config|
67
- config.api_key = 'YOUR_API_KEY'
68
- end
69
- ```
59
+ results = client.search_document_type('swiftype-api-example', 'videos', 'cat')
60
+ results['videos'] # => [{'external_id' => 'QH2-TGUlwu4', 'title' => 'Nyan Cat [original]', ... }, ... ]
61
+ results['channels'] # => nil
70
62
 
71
- Indexing:
72
- ---
63
+ Both search methods allow you to specify options to filter or sort on fields, boost the weight of certain fields, calculate faceted counts, and so on. For more details on these options, review the [Search Options](https://swiftype.com/documentation/searching).
73
64
 
74
- #### Engines:
65
+ Here is an example for showing only videos in the "Pets & Animals" category (which has ID 23):
75
66
 
76
- Search engines are the top-level container for the objects you wish to search, and most sites will have a single engine. The engines themselves contain one or more document types, each of which contain the documents themselves.
67
+ results = client.search_document_type('swiftype-api-example', 'videos', 'cat', {:filters => {'videos' => {:category_id => '23'}}})
77
68
 
78
- Create a search engine:
69
+ ### Autocomplete search
79
70
 
80
- engine = Swiftype::Engine.new(:name => 'bookstore')
81
- engine.create!
71
+ Autocomplete (also known as suggest, prefix, or type-ahead) searches can be used to implement autocompletion. They have the same functionality as full-text searches, but work on prefixes instead of all the text. Because of this, autocomplete queries only search string fields.
82
72
 
83
- Get a search engine:
73
+ You can perform a suggest query across all of your Engine's Documents:
84
74
 
85
- Swiftype::Engine.find('bookstore')
75
+ results = client.suggest("swiftype-api-example", "gla")
76
+ results['videos'] # => [{'external_id' => 'v1uyQZNg2vE', 'title' => 'How It Feels [through Glass]', ...}, ...]
86
77
 
87
- Delete a search engine:
78
+ or just for one DocumentType:
88
79
 
89
- engine = Swiftype::Engine.find('bookstore')
90
- engine.destroy!
80
+ results = client.suggest_document_type("swiftype-api-example", "videos", "gla")
81
+ results['videos'] # => [{'external_id' => 'v1uyQZNg2vE', 'title' => 'How It Feels [through Glass]', ...}, ...]
91
82
 
83
+ or add options to have more control over the results:
92
84
 
93
- #### Document Types
85
+ results = client.suggest('swiftype-api-example', 'glass', {:sort_field => {'videos' => 'view_count'}, :sort_direction => {'videos' => 'desc'}})
94
86
 
95
- Create a `document_type`:
87
+ ### Engines
96
88
 
97
- engine = Swiftype::Engine.find('bookstore')
98
- type = engine.create_document_type(:name => 'books')
89
+ Retrieve every Engine:
99
90
 
100
- Get a `document_type`:
91
+ engines = client.engines
101
92
 
102
- engine = Swiftype::Engine.find('bookstore')
103
- type = engine.document_type('books')
93
+ Create a new Engine with the name `swiftype-api-example`:
104
94
 
105
- Delete a `document_type`. Deleting a `document_type` will also delete every `document` contained within it:
95
+ engine = client.create_engine('swiftype-api-example')
106
96
 
107
- engine = Swiftype::Engine.find('bookstore')
108
- engine.destroy_document_type('books')
97
+ Retrieve an Engine by `slug` or `id`:
109
98
 
110
- or, alternatively, call destroy on the `document_type` itself:
99
+ engine = client.engine('swiftype-api-example')
100
+ engine = client.engine('5230b9102ed960ba20000021')
111
101
 
112
- engine = Swiftype::Engine.find('bookstore')
113
- type = engine.document_type('books')
114
- type.destroy!
102
+ Delete an Engine by `slug` or the `id`:
115
103
 
104
+ client.destroy_engine('swiftype-api-example')
116
105
 
117
- #### Documents
106
+ ### Document Types
118
107
 
119
- Create a `document`:
108
+ List all the
120
109
 
121
- engine = Swiftype::Engine.find('bookstore')
122
- type = engine.document_type('books')
123
- type.create_document({
124
- :external_id => '1',
125
- :fields => [
126
- {:name => 'title', :value => 'Information Retrieval', :type => 'string'},
127
- {:name => 'genre', :value => 'non-fiction', :type => 'enum'},
128
- {:name => 'author', :value => 'Stefan Buttcher', :type => 'string'},
129
- {:name => 'in_stock', :value => true, :type => 'enum'},
130
- {:name => 'on_sale', :value => false, :type => 'enum'}
131
- ]});
110
+ Retrieve `DocumentTypes`s of the Engine with the `slug` field `swiftype-api-example`:
132
111
 
133
- Get a `document`:
112
+ document_types = client.document_types('swiftype-api-example')
134
113
 
135
- engine = Swiftype::Engine.find('bookstore')
136
- type = engine.document_type('books')
137
- doc = type.document('1')
114
+ Show the second batch of documents:
138
115
 
139
- Get every `document` within a `document_type`:
116
+ document_types = client.document_types('swiftype-api-example', 2)
140
117
 
141
- engine = Swiftype::Engine.find('bookstore')
142
- type = engine.document_type('books')
143
- type.documents
118
+ Create a new DocumentType for an Engine with the name `videos`:
144
119
 
145
- Update field(s) of a `document`:
120
+ document_type = client.create_document_type('swiftype-api-example', 'videos')
146
121
 
147
- engine = Swiftype::Engine.find('bookstore')
148
- type = engine.document_type('books')
149
- doc = type.document('1')
150
- doc.update_fields!({:in_stock => false })
122
+ Retrieve an DocumentType by `slug` or `id`:
151
123
 
152
- or, alternatively, update a `document` without retrieving it first:
124
+ document_type = client.document_type('swiftype-api-example', 'videos')
153
125
 
154
- engine = Swiftype::Engine.find('bookstore')
155
- type = engine.document_type('books')
156
- type.update_document(:external_id => '1', :fields => { :in_stock => false })
126
+ Delete a DocumentType using the `slug` or `id` of it:
157
127
 
158
- you can also update multiple fields in the same call:
128
+ client.destroy_document_type('swiftype-api-example', 'videos')
159
129
 
160
- doc.update_fields({:in_stock => false, :on_sale => true })
130
+ ### Documents
161
131
 
162
- Delete a `document`:
132
+ Retrieve the first page of Documents of Engine `swiftype-api-example` and DocumentType `videos`:
163
133
 
164
- engine = Swiftype::Engine.find('bookstore')
165
- type = engine.document_type('books')
166
- doc = type.document('1')
167
- doc.destroy!
134
+ documents = client.documents('swiftype-api-example', 'videos')
168
135
 
169
- or, alternatively, delete a `document` without retrieving it first:
136
+ Retrieve a specific Document using its `id` or `external_id`:
170
137
 
171
- engine = Swiftype::Engine.find('bookstore')
172
- type = engine.document_type('books')
173
- type.destroy_document('1')
138
+ document = client.document('swiftype-api-example', 'videos', 'FHtvDA0W34I')
174
139
 
140
+ Create a new Document with mandatory `external_id` and user-defined fields:
175
141
 
176
- #### Bulk Operations
142
+ document = client.create_document('swiftype-api-example', 'videos', {
143
+ :external_id => 'FHtvDA0W34I',
144
+ :fields => [
145
+ {:name => 'title', :value => "Felix Baumgartner's supersonic freefall from 128k' - Mission Highlights", :type => 'string'},
146
+ {:name => 'url', :value => 'http://www.youtube.com/watch?v=FHtvDA0W34I', :type => 'enum'},
147
+ {:name => 'chanel_id', :value => 'UCblfuW_4rakIf2h6aqANefA', :type => 'enum'}
148
+ ]})
177
149
 
178
- Bulk operations will allow you to perform rapid indexing updates and avoid the latency overhead of making repeated requests.
150
+ Create multiple Documents at once and return status for each Document creation:
179
151
 
180
- Create `document`s in bulk:
152
+ response = client.create_documents('swiftype-api-example', 'videos', [{
153
+ :external_id => 'FHtvDA0W34I',
154
+ :fields => [
155
+ {:name => 'title', :value => "Felix Baumgartner's supersonic freefall from 128k' - Mission Highlights", :type => 'string'},
156
+ {:name => 'url', :value => 'http://www.youtube.com/watch?v=FHtvDA0W34I', :type => 'enum'},
157
+ {:name => 'chanel_id', :value => 'UCblfuW_4rakIf2h6aqANefA', :type => 'enum'}
158
+ ]}, {
159
+ :external_id => 'dMH0bHeiRNg',
160
+ :fields => [
161
+ {:name => 'title', :value => 'Evolution of Dance - By Judson Laipply', :type => 'string'},
162
+ {:name => 'url', :value => 'http://www.youtube.com/watch?v='dMH0bHeiRNg', :type => 'enum'},
163
+ {:name => 'chanel_id', :value => UC5B9H4l2vtgo7cAoExcFh-w', :type => 'enum'}
164
+ ]}])
165
+ #=> [true, true]
181
166
 
182
- engine = Swiftype::Engine.find('bookstore')
183
- type = engine.document_type('books')
184
- type.create_documents([{
185
- :external_id => '2',
186
- :fields => [
187
- {:name => 'title', :value => 'Lucene in Action', :type => 'string'},
188
- {:name => 'genre', :value => 'non-fiction', :type => 'enum'},
189
- {:name => 'author', :value => 'Michael McCandless', :type => 'string'},
190
- {:name => 'in_stock', :value => true, :type => 'enum'},
191
- {:name => 'on_sale', :value => false, :type => 'enum'}
192
- ]},{
193
- :external_id => '3',
194
- :fields => [
195
- {:name => 'title', :value => 'MongoDB in Action', :type => 'string'},
196
- {:name => 'genre', :value => 'non-fiction', :type => 'enum'},
197
- {:name => 'author', :value => 'Kyle Banker', :type => 'string'},
198
- {:name => 'in_stock', :value => true, :type => 'enum'},
199
- {:name => 'on_sale', :value => false, :type => 'enum'}
200
- ]},{
201
- :external_id => '4',
202
- :fields => [
203
- {:name => 'title', :value => 'The Great Gatsby', :type => 'string'},
204
- {:name => 'genre', :value => 'fiction', :type => 'enum'},
205
- {:name => 'author', :value => 'F. Scott Fitzgerald', :type => 'string'},
206
- {:name => 'in_stock', :value => true, :type => 'enum'},
207
- {:name => 'on_sale', :value => false, :type => 'enum'}
208
- ]}
209
- ])
167
+ Update fields of an existing Document specified by `id` or `external_id`:
210
168
 
211
- Update `document`s in bulk:
169
+ client.update_document('swiftype-api-example', 'videos', 'FHtvDA0W34I', {:title =>'New Title'})
212
170
 
213
- engine = Swiftype::Engine.find('bookstore')
214
- type = engine.document_type('books')
215
- type.update_documents([
216
- {:external_id => '2', :fields => {:in_stock => false, :on_sale => 'false'}},
217
- {:external_id => '3', :fields => {:in_stock => false, :on_sale => 'false'}}
218
- ])
171
+ **NOTE:** A field must already exist on a Document in order to update it.
219
172
 
220
- Delete `document`s in bulk:
173
+ Update multiple Documents at once:
221
174
 
222
- engine = Swiftype::Engine.find('bookstore')
223
- type = engine.document_type('books')
224
- type.destroy_documents(['1','2','3','4'])
175
+ response = client.update_documents('swiftype-api-example','videos', [
176
+ {:external_id => 'FHtvDA0W34I', :fields => {:view_count => 32874417}},
177
+ {:external_id => 'dMH0bHeiRNg', :fields => {:view_count => 98323493}}
178
+ ])
179
+ #=> [true, true]
225
180
 
181
+ Create or update a Document:
226
182
 
227
- Searching:
228
- ---
183
+ document = client.create_or_update_document('swiftype-api-example', 'videos', {
184
+ :external_id => 'FHtvDA0W34I',
185
+ :fields => [
186
+ {:name => 'title', :value => "Felix Baumgartner's supersonic freefall from 128k' - Mission Highlights", :type => 'string'},
187
+ {:name => 'url', :value => 'http://www.youtube.com/watch?v=FHtvDA0W34I', :type => 'enum'},
188
+ {:name => 'chanel_id', :value => 'UCblfuW_4rakIf2h6aqANefA', :type => 'enum'}
189
+ ]})
229
190
 
230
- #### Full text search
191
+ Create or update multiple `Documents` at once:
231
192
 
232
- Search a `document_type` for the query "lucene":
193
+ response = client.create_or_update_documents('swiftype-api-example', 'videos', [{
194
+ :external_id => 'FHtvDA0W34I',
195
+ :fields => [
196
+ {:name => 'title', :value => "Felix Baumgartner's supersonic freefall from 128k' - Mission Highlights", :type => 'string'},
197
+ {:name => 'url', :value => 'http://www.youtube.com/watch?v=FHtvDA0W34I', :type => 'enum'},
198
+ {:name => 'chanel_id', :value => 'UCblfuW_4rakIf2h6aqANefA', :type => 'enum'}
199
+ ]}, {
200
+ :external_id => 'dMH0bHeiRNg',
201
+ :fields => [
202
+ {:name => 'title', :value => 'Evolution of Dance - By Judson Laipply', :type => 'string'},
203
+ {:name => 'url', :value => 'http://www.youtube.com/watch?v='dMH0bHeiRNg', :type => 'enum'},
204
+ {:name => 'chanel_id', :value => UC5B9H4l2vtgo7cAoExcFh-w', :type => 'enum'}
205
+ ]}])
233
206
 
234
- engine = Swiftype::Engine.find('bookstore')
235
- type = engine.document_type('books')
236
- results = type.search("lucene")
207
+ Destroy a Document by external_id:
237
208
 
238
- Searches return a `ResultSet` object from which you retrieve the results. Results are grouped by their `DocumentType`, so you retrieve the results for a specific `DocumentType` as follows:
209
+ client.destroy_document('swiftype-api-example','videos','dFs9WO2B8uI')
239
210
 
240
- resultset = type.search('lucene')
241
- book_results = resultset['books']
242
- book_results.each do |book|
243
- puts book.title
244
- puts book.author
245
- puts book.genre
246
- end
211
+ Destroy multiple Documents at once:
247
212
 
248
- The `ResultSet` object also contains meta data for the search, such as pagination and facets if the user has specified them.
213
+ response = client.destroy_documents('swiftype-api-example', 'videos', ['QH2-TGUlwu4, 'v1uyQZNg2vE', 'ik5sdwYZ01Q'])
214
+ #=> [true, true, true]
249
215
 
250
- #### Pagination
216
+ ### Domains
251
217
 
252
- To get pagination information from a `ResultSet`, you call the `num_pages`, `current_page`, and `per_page` methods. For example:
218
+ **Domains** are a feature of crawler-based engines that represent a web site to index with the Swiftype web crawler.
253
219
 
254
- resultset = type.search('lucene')
255
- puts "Current page of results: #{resultset.current_page}"
256
- puts "Total pages in this result set: #{resultset.num_pages}"
257
- puts "Number of results per page: #{resultset.per_page}"
220
+ Retrieve all Domains of Engine `websites`:
258
221
 
259
- #### Search Options
222
+ domains = client.domains('websites')
223
+ #=> [{"id"=>"513fcc042ed960c186000001", "engine_id"=>"513fcc042ed960114400000d", "submitted_url"=>"http://example.com/", "start_crawl_url"=>"http://www.example.com/", "crawling"=>false, "document_count"=>337, "updated_at"=>"2013-03-13T00:48:32Z"}, ...]
260
224
 
261
- You can pass the following options to the search method: `page`, `per_page`, `fetch_fields`, `search_fields`, `filters`, and `facets`.
225
+ Retrieve a specific Domain by `id`:
262
226
 
263
- * `page` should be an integer of the page of results you want
264
- * `per_page` should be an integer of the number of results you want from each page
265
- * `fetch_fields` is a hash containing arrays of the fields you want to have returned for each object of each document_type
266
- * `search_fields` is a hash containing arrays of the fields you want to match your query against for each object of each document_type
267
- * `functional_boosts` is a hash containing boosts that are to be applied to numerically valued fields
268
- * `filters` is a hash specifying additional conditions that should be applied to your query for each document_type
269
- * `facets` is a hash specifying fields for faceted counts for each document type
227
+ domain = client.domain('websites', '513fcc042ed960c186000001'')
228
+ #=> {"id"=>"513fcc042ed960c186000001", "engine_id"=>"513fcc042ed960114400000d", "submitted_url"=>"http://example.com/", "start_crawl_url"=>"http://www.example.com/", "crawling"=>false, "document_count"=>337, "updated_at"=>"2013-03-13T00:48:32Z"}
270
229
 
271
- An example of using search options is as follows:
230
+ Create a new Domain with the URL `https://swiftype.com` and start crawling:
272
231
 
273
- resultset = type.search('lucene', :filters => { :books => { :in_stock => false, :genre => 'fiction' }}, :per_page => 10, :page => 2, :fetch_fields => {:books => ['title','genre']}, :search_fields => {:books => ['title']})
232
+ domain = client.create_domain('websites', 'https://swiftype.com')
274
233
 
275
- Filters also support datetime range queries. For example, to return only those books with an `updated_at` field between `2012-02-16` and now, use the following filter:
234
+ Delete a Domain using its `id`:
276
235
 
277
- resultset = type.search('lucene', :filters => { :books => { :updated_at => '[2012-02-16 TO *]' }})
236
+ client.destroy_domain('websites', '513fcc042ed960c186000001')
278
237
 
279
- See the (Swiftype Documentation)[http://swiftype.com/documentation/searching] for more details and examples of search options.
238
+ Initiate a recrawl of a specific Domain using its `id`:
280
239
 
240
+ client.recrawl_domain('websites', '513fcc042ed960c186000001')
281
241
 
282
- ##### Functional Boosts
242
+ Add or update a URL for a Domain:
283
243
 
284
- Functional boosts allow you to boost result scores based on some numerically valued field. For example, you might want your search engine to return the most popular books first, so you would boost results on the `total_purchases` field, which contains an `integer` of the total number of purchases of that book:
244
+ client.crawl_url('websites', '513fcc042ed960c186000001', 'https://swiftype.com/new/path.html')
285
245
 
286
- resultset = type.search('lucene', :functional_boosts => { :books => { :total_purchases => 'logarithmic' }})
246
+ ### Analytics
287
247
 
288
- There are 3 types of functional boosts:
248
+ Swiftype records the number of searches, autoselects (when a user clicks a link from a suggest result), and clickthroughs (when a user clicks through to an item from a search result list. You can view this information in your Swiftype Dashboard, but you can also export it using the API.
289
249
 
290
- * `logarithmic` - multiplies the original score by log(numeric_value)
291
- * `exponential` - multiplies the original score by exp(numeric_value)
292
- * `linear` - multiplies the original score numeric_value
250
+ To get the number of searches per day from an Engine in the last 14 days:
293
251
 
294
- Functional boosts may be applied to `integer` and `float` valued fields.
252
+ searches = client.analytics_searches('swiftype-api-example')
253
+ #=> [['2013-09-13', '123'], [2013-09-12', '94'], ... ]
295
254
 
296
- ##### Facets
255
+ You can also use a specific start and/or end date:
297
256
 
298
- You may get facets for your search results by passing the facets option when you search. For example, to get aggregate counts for the number of results in each genre, use the following:
257
+ searches = client.analytics_searches('swiftype-api-example', '2013-01-01', '2013-01-07')
299
258
 
300
- resultset = type.search('lucene', :facets => { :books => ['genre']})
259
+ To get the number of autoselects in the past 14 days:
301
260
 
302
- You can retrieve the facet counts from the `ResultSet` as follows:
261
+ autoselects = client.analytics_autoselects('swiftype-api-example')
303
262
 
304
- resultset = type.search('lucene', :facets => { :books => ['genre']})
305
- resultset.facets('books')
306
- => {"genre"=>{"fiction"=>5, "non-fiction"=>2, "political"=>1, "fantasy"=>1}}
263
+ As with searches you can also limit by start and/or end date:
307
264
 
308
- #### Autocomplete
265
+ autoselects = client.analytics_autoselects('swiftype-api-example', '2013-01-01', '2013-01-07')
309
266
 
310
- Get autocomplete suggestions from a `document_type` for the prefix "act"
267
+ If you are interested in the top queries for your Engine you can use:
311
268
 
312
- engine = Swiftype::Engine.find('bookstore')
313
- type = engine.document_type('books')
314
- results = type.suggest("act")
269
+ top_queries = client.analytics_top_queries('swiftype-api-example')
270
+ # => [['query term', 123], ['another query', 121], ['yet another query', 92], ...]
315
271
 
316
- The suggest method also accepts the same options specified for the search method above.
272
+ To see more top queries you can paginate through them using:
317
273
 
274
+ top_queries = client.analytics_top_queries('swiftype-api-example', {:page => 2})
318
275
 
319
- Simple Client:
320
- ===
321
- The Simple Client is a convenience class that gives you basic, direct access to the Swiftype REST API, without mapping each call to the intermediate objects seen in the examples above. These methods will be more performant, because they avoid unnecessary round-trips to the server, but you will also have to provide more information to each call. Choose whatever suites your use-case.
276
+ Or you can get the top queries in a specific date range:
322
277
 
323
- #### Create a Simple Client
278
+ top_queries = client.analytics_top_queries('swiftype-api-example', {:start_date => '2013-01-01', :end_date => '2013-01-07'})
324
279
 
325
- client = Swiftype::Easy.new
280
+ If you want to improve you search results, you should always have a look at search queries, that return no results and perhaps add some Documents that match for this query or use our pining feature to add Documents for this query:
326
281
 
327
- #### Search
282
+ top_no_result_queries = client.analytics_top_no_result_queries('swiftype-api-example')
328
283
 
329
- results = client.search('bookstore',{SEARCH QUERY} [, OPTIONAL SEARCH OPTIONS])
284
+ You can also specifiy a date range for queries without results:
330
285
 
331
- #### Autocomplete
286
+ top_no_result_queries = client.analytics_top_no_result_queries('swiftype-api-example', {:start_date => '2013-01-01', :end_date => '2013-01-07'})
332
287
 
333
- results = client.suggest('bookstore',{AUTOCOMPLETE PREFIX QUERY} [, OPTIONAL SEARCH OPTIONS])
288
+ ## Migrating from previous versions
334
289
 
335
- #### Engines
290
+ swiftype-rb 1.0.0 has been rewritten to be simpler and easier to use. However, it is not compatable with the previous version, 0.0.5.
336
291
 
337
- client.engines # retrieves every engine
338
- client.create_engine(:name => 'bookstore')
339
- client.destroy_engine('bookstore')
292
+ To upgrade from the old version of swiftype-rb:
340
293
 
341
- #### Document Types
294
+ * If you previously used the `Swiftype` client, migrate your API calls to the `Swiftype::Client` format.
295
+ * If you previously used the `Swiftype::Easy` client, change `Swiftype::Easy` to `Swiftype::Client`. Almost all method calls should be the same (there are a few minor changes).
342
296
 
343
- client.document_types('bookstore')
344
- client.create_document_type('bookstore', :name => 'books')
345
- client.destroy_document_type('bookstore', 'books')
297
+ Additionally, the result object returned by search methods (for example, the old Swiftype gem's `Engine#search` or `Swiftype::Easy#search` methods) returns results in a different way. Instead of being an array of `Swiftype::Document` objects, it will be an array of Hashes.
346
298
 
347
- #### Documents
299
+ Code like this:
348
300
 
349
- # retrieve all documents
350
- client.documents('bookstore', 'books')
301
+ client = Swiftype::Easy.new
302
+ results = client.search("engine_slug", "search term")
303
+ results.each do |result|
304
+ puts result.title
305
+ end
351
306
 
352
- # create a document
353
- client.create_document('bookstore', 'books', {
354
- :external_id => '1',
355
- :fields => [
356
- {:name => 'title', :value => 'Information Retrieval', :type => 'string'},
357
- {:name => 'genre', :value => 'non-fiction', :type => 'enum'},
358
- {:name => 'author', :value => 'Stefan Buttcher', :type => 'string'},
359
- {:name => 'in_stock', :value => true, :type => 'enum'},
360
- {:name => 'on_sale', :value => false, :type => 'enum'}
361
- ]})
307
+ Should be changed to this:
362
308
 
363
- # create documents in bulk
364
- client.create_documents('bookstore', 'books', [{
365
- :external_id => '2',
366
- :fields => [
367
- {:name => 'title', :value => 'Lucene in Action', :type => 'string'},
368
- {:name => 'genre', :value => 'non-fiction', :type => 'enum'},
369
- {:name => 'author', :value => 'Michael McCandless', :type => 'string'},
370
- {:name => 'in_stock', :value => true, :type => 'enum'},
371
- {:name => 'on_sale', :value => false, :type => 'enum'}
372
- ]},{
373
- :external_id => '3',
374
- :fields => [
375
- {:name => 'title', :value => 'MongoDB in Action', :type => 'string'},
376
- {:name => 'genre', :value => 'non-fiction', :type => 'enum'},
377
- {:name => 'author', :value => 'Kyle Banker', :type => 'string'},
378
- {:name => 'in_stock', :value => true, :type => 'enum'},
379
- {:name => 'on_sale', :value => false, :type => 'enum'}
380
- ]}])
309
+ client = Swiftype::Client.new
310
+ results = client.search("engine_slug", "search term")
311
+ results.each do |result|
312
+ puts result['title']
313
+ end
381
314
 
382
- # update a document
383
- client.update_document('bookstore','books','1', { :in_stock => false })
315
+ If you are not able to upgrade, lock your gem version to 0.0.5 by adding this to your Gemfile:
384
316
 
385
- # update documents in bulk
386
- client.update_documents('bookstore','books', [
387
- {:external_id => '2', :fields => {:in_stock => false}},
388
- {:external_id => '3', :fields => {:in_stock => true}}
389
- ])
317
+ gem 'swiftype, '= 0.0.5'
390
318
 
391
- # create or update a document
392
- client.create_or_update_document('bookstore', 'books', {
393
- :external_id => '1',
394
- :fields => [
395
- {:name => 'title', :value => 'Information Retrieval', :type => 'string'},
396
- {:name => 'genre', :value => 'non-fiction', :type => 'enum'},
397
- {:name => 'author', :value => 'Stefan Buttcher', :type => 'string'},
398
- {:name => 'in_stock', :value => false, :type => 'enum'},
399
- {:name => 'on_sale', :value => true, :type => 'enum'}
400
- ]})
319
+ To upgrade from the beta swiftype-easy-rb library (which was the precursor of swiftype-rb 1.0), change `Swiftype::Easy` to `Swiftype::Client` and move your configuration from the `Swiftype::Easy` module to the `Swiftype` module. For example:
401
320
 
402
- # destroy a document
403
- client.destroy_document('bookstore','books','1')
321
+ Swiftype:Easy.configure do |configure|
322
+ config.api_key = 'your_api_key'
323
+ end
404
324
 
405
- # destroy documents in bulk
406
- client.destroy_documents('bookstore','books',['1','2','3'])
325
+ can be converted to
407
326
 
327
+ Swiftype.configure do |config|
328
+ config.api_key = 'your_api_key'
329
+ end
408
330
 
409
- Todo
410
- ===
331
+ or simply `Swiftype.api_key = 'your_api_key'`.
411
332
 
412
- + Tests!
333
+ ## Development
413
334
 
335
+ You can run tests with `rspec`. All HTTP interactions are stubbed out using VCR.
414
336
 
415
- Questions?
416
- ===
417
- Get in touch! We would be happy to help you get up and running.
337
+ To contribute code to this gem, please fork the repository and submit a pull request.
418
338
 
419
- [Quin](mailto:quin@swiftype.com) and [Matt](mailto:matt@swiftype.com) from [Swiftype](http://swiftype.com)