algoliasearch-rails 1.16.3 → 1.25.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.travis.yml +56 -42
- data/{ChangeLog → CHANGELOG.MD} +163 -1
- data/Gemfile +25 -6
- data/Gemfile.lock +144 -325
- data/LICENSE +6 -7
- data/README.md +448 -306
- data/algoliasearch-rails.gemspec +10 -8
- data/lib/algoliasearch-rails.rb +285 -117
- data/lib/algoliasearch/configuration.rb +3 -1
- data/lib/algoliasearch/tasks/algoliasearch.rake +6 -2
- data/lib/algoliasearch/utilities.rb +29 -3
- data/lib/algoliasearch/version.rb +3 -0
- data/spec/spec_helper.rb +26 -4
- data/vendor/assets/javascripts/algolia/algoliasearch.angular.js +23 -12
- data/vendor/assets/javascripts/algolia/algoliasearch.angular.min.js +2 -2
- data/vendor/assets/javascripts/algolia/algoliasearch.jquery.js +23 -12
- data/vendor/assets/javascripts/algolia/algoliasearch.jquery.min.js +2 -2
- data/vendor/assets/javascripts/algolia/algoliasearch.js +22 -12
- data/vendor/assets/javascripts/algolia/algoliasearch.min.js +2 -2
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.angular.js +23 -12
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.angular.min.js +2 -2
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.jquery.js +23 -12
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.jquery.min.js +2 -2
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.js +22 -12
- data/vendor/assets/javascripts/algolia/v2/algoliasearch.min.js +2 -2
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.angular.js +2020 -1301
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.angular.min.js +3 -3
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.jquery.js +2019 -1300
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.jquery.min.js +3 -3
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.js +2003 -1284
- data/vendor/assets/javascripts/algolia/v3/algoliasearch.min.js +3 -3
- metadata +19 -15
- data/VERSION +0 -1
data/LICENSE
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
|
1
|
+
MIT License
|
2
2
|
|
3
|
-
Copyright (c) 2013 Algolia
|
4
|
-
http://www.algolia.com/
|
3
|
+
Copyright (c) 2013-Present Algolia
|
5
4
|
|
6
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
7
6
|
of this software and associated documentation files (the "Software"), to deal
|
@@ -10,13 +9,13 @@ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
9
|
copies of the Software, and to permit persons to whom the Software is
|
11
10
|
furnished to do so, subject to the following conditions:
|
12
11
|
|
13
|
-
The above copyright notice and this permission notice shall be included in
|
14
|
-
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
15
14
|
|
16
15
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
16
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
17
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
21
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
22
|
-
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -1,44 +1,98 @@
|
|
1
|
-
|
1
|
+
<p align="center">
|
2
|
+
<a href="https://www.algolia.com">
|
3
|
+
<img alt="Algolia for Rails" src="https://raw.githubusercontent.com/algolia/algoliasearch-client-common/master/banners/rails.png" >
|
4
|
+
</a>
|
2
5
|
|
3
|
-
Algolia
|
4
|
-
==================
|
6
|
+
<h4 align="center">The perfect starting point to integrate <a href="https://algolia.com" target="_blank">Algolia</a> within your Rails project</h4>
|
5
7
|
|
6
|
-
|
8
|
+
<p align="center">
|
9
|
+
<a href="https://travis-ci.org/algolia/algoliasearch-rails"><img src="https://img.shields.io/travis/algolia/algoliasearch-rails/master.svg" alt="Build Status"></img></a>
|
10
|
+
<a href="http://badge.fury.io/rb/algoliasearch-rails"><img src="https://badge.fury.io/rb/algoliasearch-rails.svg" alt="Gem Version"></img></a>
|
11
|
+
<a href="https://codeclimate.com/github/algolia/algoliasearch-rails"><img src="https://codeclimate.com/github/algolia/algoliasearch-rails.svg" alt="Code Climate"></img></a>
|
12
|
+
<img src="https://img.shields.io/badge/ActiveRecord-yes-blue.svg?style=flat-square" alt="ActiveRecord"></img>
|
13
|
+
<img src="https://img.shields.io/badge/Mongoid-yes-blue.svg?style=flat-square" alt="Mongoid"></img>
|
14
|
+
<img src="https://img.shields.io/badge/Sequel-yes-blue.svg?style=flat-square" alt="Sequel"></img>
|
15
|
+
</p>
|
16
|
+
</p>
|
7
17
|
|
8
|
-
|
18
|
+
<p align="center">
|
19
|
+
<a href="https://www.algolia.com/doc/framework-integration/rails/getting-started/setup/?language=ruby" target="_blank">Documentation</a> •
|
20
|
+
<a href="https://discourse.algolia.com" target="_blank">Community Forum</a> •
|
21
|
+
<a href="http://stackoverflow.com/questions/tagged/algolia" target="_blank">Stack Overflow</a> •
|
22
|
+
<a href="https://github.com/algolia/algoliasearch-rails/issues" target="_blank">Report a bug</a> •
|
23
|
+
<a href="https://www.algolia.com/doc/framework-integration/rails/troubleshooting/faq/" target="_blank">FAQ</a> •
|
24
|
+
<a href="https://www.algolia.com/support" target="_blank">Support</a>
|
25
|
+
</p>
|
9
26
|
|
10
|
-
You might be interested in the sample Ruby on Rails application providing a `autocomplete.js`-based auto-completion and `instantsearch.js`-based instant search results page: [algoliasearch-rails-example](https://github.com/algolia/algoliasearch-rails-example/).
|
11
27
|
|
12
|
-
|
28
|
+
This gem let you easily integrate the Algolia Search API to your favorite ORM. It's based on the [algoliasearch-client-ruby](https://github.com/algolia/algoliasearch-client-ruby) gem.
|
29
|
+
Rails 3.x, 4.x and 5.x are all supported.
|
13
30
|
|
14
|
-
|
31
|
+
You might be interested in the sample Ruby on Rails application providing a `autocomplete.js`-based auto-completion and `InstantSearch.js`-based instant search results page: [algoliasearch-rails-example](https://github.com/algolia/algoliasearch-rails-example/).
|
15
32
|
|
16
|
-
Table of Content
|
17
|
-
=============
|
18
33
|
|
19
|
-
1. [Install](#install)
|
20
|
-
1. [Setup](#setup)
|
21
|
-
1. [Quick Start](#quick-start)
|
22
|
-
1. [Options](#options)
|
23
|
-
1. [Configuration example](#configuration-example)
|
24
|
-
1. [Indexing](#indexing)
|
25
|
-
1. [Master/Slave](#masterslave)
|
26
|
-
1. [Share a single index](#share-a-single-index)
|
27
|
-
1. [Target multiple indexes](#target-multiple-indexes)
|
28
|
-
1. [Tags](#tags)
|
29
|
-
1. [Search](#search)
|
30
|
-
1. [Faceting](#faceting)
|
31
|
-
1. [Facet search](#facet-search)
|
32
|
-
1. [Group by](#group-by)
|
33
|
-
1. [Geo-search](#geo-search)
|
34
|
-
1. [Caveats](#caveats)
|
35
|
-
1. [Note on testing](#note-on-testing)
|
36
34
|
|
37
|
-
|
35
|
+
## API Documentation
|
38
36
|
|
39
|
-
|
37
|
+
You can find the full reference on [Algolia's website](https://www.algolia.com/doc/framework-integration/rails/).
|
40
38
|
|
41
|
-
|
39
|
+
|
40
|
+
|
41
|
+
1. **[Setup](#setup)**
|
42
|
+
* [Install](#install)
|
43
|
+
* [Configuration](#configuration)
|
44
|
+
* [Timeouts](#timeouts)
|
45
|
+
* [Notes](#notes)
|
46
|
+
|
47
|
+
1. **[Usage](#usage)**
|
48
|
+
* [Index Schema](#index-schema)
|
49
|
+
* [Relevancy](#relevancy)
|
50
|
+
* [Indexing](#indexing)
|
51
|
+
* [Frontend Search (realtime experience)](#frontend-search-realtime-experience)
|
52
|
+
* [Backend Search](#backend-search)
|
53
|
+
* [Backend Pagination](#backend-pagination)
|
54
|
+
* [Tags](#tags)
|
55
|
+
* [Faceting](#faceting)
|
56
|
+
* [Faceted search](#faceted-search)
|
57
|
+
* [Group by](#group-by)
|
58
|
+
* [Geo-Search](#geo-search)
|
59
|
+
|
60
|
+
1. **[Options](#options)**
|
61
|
+
* [Auto-indexing & asynchronism](#auto-indexing--asynchronism)
|
62
|
+
* [Custom index name](#custom-index-name)
|
63
|
+
* [Per-environment indices](#per-environment-indices)
|
64
|
+
* [Custom attribute definition](#custom-attribute-definition)
|
65
|
+
* [Nested objects/relations](#nested-objectsrelations)
|
66
|
+
* [Custom <code>objectID</code>](#custom-objectid)
|
67
|
+
* [Restrict indexing to a subset of your data](#restrict-indexing-to-a-subset-of-your-data)
|
68
|
+
* [Sanitizer](#sanitizer)
|
69
|
+
* [UTF-8 Encoding](#utf-8-encoding)
|
70
|
+
* [Exceptions](#exceptions)
|
71
|
+
* [Configuration example](#configuration-example)
|
72
|
+
|
73
|
+
1. **[Indices](#indices)**
|
74
|
+
* [Manual indexing](#manual-indexing)
|
75
|
+
* [Manual removal](#manual-removal)
|
76
|
+
* [Reindexing](#reindexing)
|
77
|
+
* [Clearing an index](#clearing-an-index)
|
78
|
+
* [Using the underlying index](#using-the-underlying-index)
|
79
|
+
* [Primary/replica](#primaryreplica)
|
80
|
+
* [Share a single index](#share-a-single-index)
|
81
|
+
* [Target multiple indices](#target-multiple-indices)
|
82
|
+
|
83
|
+
1. **[Testing](#testing)**
|
84
|
+
* [Notes](#notes)
|
85
|
+
|
86
|
+
1. **[Troubleshooting](#troubleshooting)**
|
87
|
+
* [Frequently asked questions](#frequently-asked-questions)
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
# Setup
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
## Install
|
42
96
|
|
43
97
|
```sh
|
44
98
|
gem install algoliasearch-rails
|
@@ -56,20 +110,51 @@ And run:
|
|
56
110
|
bundle install
|
57
111
|
```
|
58
112
|
|
59
|
-
|
113
|
+
## Configuration
|
60
114
|
|
61
115
|
Create a new file <code>config/initializers/algoliasearch.rb</code> to setup your <code>APPLICATION_ID</code> and <code>API_KEY</code>.
|
62
116
|
|
63
|
-
|
64
117
|
```ruby
|
65
118
|
AlgoliaSearch.configuration = { application_id: 'YourApplicationID', api_key: 'YourAPIKey' }
|
66
119
|
```
|
67
120
|
|
68
121
|
The gem is compatible with [ActiveRecord](https://github.com/rails/rails/tree/master/activerecord), [Mongoid](https://github.com/mongoid/mongoid) and [Sequel](https://github.com/jeremyevans/sequel).
|
69
122
|
|
70
|
-
##
|
123
|
+
## Timeouts
|
124
|
+
|
125
|
+
You can configure a various timeout thresholds by setting the following options at initialization time:
|
126
|
+
|
127
|
+
```ruby
|
128
|
+
AlgoliaSearch.configuration = {
|
129
|
+
application_id: 'YourApplicationID',
|
130
|
+
api_key: 'YourAPIKey',
|
131
|
+
connect_timeout: 2,
|
132
|
+
receive_timeout: 30,
|
133
|
+
send_timeout: 30,
|
134
|
+
batch_timeout: 120,
|
135
|
+
search_timeout: 5
|
136
|
+
}
|
137
|
+
```
|
138
|
+
|
139
|
+
## Notes
|
140
|
+
|
141
|
+
This gem makes extensive use of Rails' callbacks to trigger the indexing tasks. If you're using methods bypassing `after_validation`, `before_save` or `after_commit` callbacks, it will not index your changes. For example: `update_attribute` doesn't perform validations checks, to perform validations when updating use `update_attributes`.
|
71
142
|
|
72
|
-
|
143
|
+
All methods injected by the `AlgoliaSearch` module are prefixed by `algolia_` and aliased to the associated short names if they aren't already defined.
|
144
|
+
|
145
|
+
```ruby
|
146
|
+
Contact.algolia_reindex! # <=> Contact.reindex!
|
147
|
+
|
148
|
+
Contact.algolia_search("jon doe") # <=> Contact.search("jon doe")
|
149
|
+
```
|
150
|
+
|
151
|
+
|
152
|
+
|
153
|
+
# Usage
|
154
|
+
|
155
|
+
|
156
|
+
|
157
|
+
## Index Schema
|
73
158
|
|
74
159
|
The following code will create a <code>Contact</code> index and add search capabilities to your <code>Contact</code> model:
|
75
160
|
|
@@ -78,7 +163,7 @@ class Contact < ActiveRecord::Base
|
|
78
163
|
include AlgoliaSearch
|
79
164
|
|
80
165
|
algoliasearch do
|
81
|
-
|
166
|
+
attributes :first_name, :last_name, :email
|
82
167
|
end
|
83
168
|
end
|
84
169
|
```
|
@@ -112,7 +197,7 @@ class Product < ActiveRecord::Base
|
|
112
197
|
end
|
113
198
|
```
|
114
199
|
|
115
|
-
|
200
|
+
## Relevancy
|
116
201
|
|
117
202
|
We provide many ways to configure your index allowing you to tune your overall index relevancy. The most important ones are the **searchable attributes** and the attributes reflecting **record popularity**.
|
118
203
|
|
@@ -124,11 +209,11 @@ class Product < ActiveRecord::Base
|
|
124
209
|
# list of attribute used to build an Algolia record
|
125
210
|
attributes :title, :subtitle, :description, :likes_count, :seller_name
|
126
211
|
|
127
|
-
# the
|
212
|
+
# the `searchableAttributes` (formerly known as attributesToIndex) setting defines the attributes
|
128
213
|
# you want to search in: here `title`, `subtitle` & `description`.
|
129
214
|
# You need to list them by order of importance. `description` is tagged as
|
130
215
|
# `unordered` to avoid taking the position of a match into account in that attribute.
|
131
|
-
|
216
|
+
searchableAttributes ['title', 'subtitle', 'unordered(description)']
|
132
217
|
|
133
218
|
# the `customRanking` setting defines the ranking criteria use to compare two matching
|
134
219
|
# records in case their text-relevance is equal. It should reflect your record popularity.
|
@@ -138,7 +223,7 @@ class Product < ActiveRecord::Base
|
|
138
223
|
end
|
139
224
|
```
|
140
225
|
|
141
|
-
|
226
|
+
## Indexing
|
142
227
|
|
143
228
|
To index a model, simple call `reindex` on the class:
|
144
229
|
|
@@ -156,11 +241,11 @@ algolia_models = ActiveRecord::Base.descendants.select{ |model| model.respond_to
|
|
156
241
|
algolia_models.each(&:reindex)
|
157
242
|
```
|
158
243
|
|
159
|
-
|
244
|
+
## Frontend Search (realtime experience)
|
160
245
|
|
161
246
|
Traditional search implementations tend to have search logic and functionality on the backend. This made sense when the search experience consisted of a user entering a search query, executing that search, and then being redirected to a search result page.
|
162
247
|
|
163
|
-
Implementing search on the backend is no longer necessary. In fact, in most cases it is harmful to performance because of added network and processing latency. We highly recommend the usage of our [JavaScript API Client](https://github.com/algolia/algoliasearch-client-
|
248
|
+
Implementing search on the backend is no longer necessary. In fact, in most cases it is harmful to performance because of added network and processing latency. We highly recommend the usage of our [JavaScript API Client](https://github.com/algolia/algoliasearch-client-javascript) issuing all search requests directly from the end user's browser, mobile device, or client. It will reduce the overall search latency while offloading your servers at the same time.
|
164
249
|
|
165
250
|
The JS API client is part of the gem, just require `algolia/v3/algoliasearch.min` somewhere in your JavaScript manifest, for example in `application.js` if you are using Rails 3.1+:
|
166
251
|
|
@@ -182,23 +267,58 @@ index.search('something', { hitsPerPage: 10, page: 0 })
|
|
182
267
|
});
|
183
268
|
```
|
184
269
|
|
185
|
-
**We recently (March 2015) released a new version (V3) of our JavaScript client, if you were using our previous version (V2), [read the migration guide](https://github.com/algolia/algoliasearch-client-
|
270
|
+
**We recently (March 2015) released a new version (V3) of our JavaScript client, if you were using our previous version (V2), [read the migration guide](https://github.com/algolia/algoliasearch-client-javascript/wiki/Migration-guide-from-2.x.x-to-3.x.x)**
|
186
271
|
|
187
|
-
|
272
|
+
## Backend Search
|
188
273
|
|
189
|
-
|
274
|
+
***Notes:*** We recommend the usage of our [JavaScript API Client](https://github.com/algolia/algoliasearch-client-javascript) to perform queries directly from the end-user browser without going through your server.
|
275
|
+
|
276
|
+
A search returns ORM-compliant objects reloading them from your database. We recommend the usage of our [JavaScript API Client](https://github.com/algolia/algoliasearch-client-javascript) to perform queries to decrease the overall latency and offload your servers.
|
190
277
|
|
191
278
|
```ruby
|
192
|
-
|
279
|
+
hits = Contact.search("jon doe")
|
280
|
+
p hits
|
281
|
+
p hits.raw_answer # to get the original JSON raw answer
|
193
282
|
```
|
194
283
|
|
195
|
-
|
284
|
+
A `highlight_result` attribute is added to each ORM object:
|
196
285
|
|
197
286
|
```ruby
|
198
|
-
|
287
|
+
hits[0].highlight_result['first_name']['value']
|
199
288
|
```
|
200
289
|
|
201
|
-
|
290
|
+
If you want to retrieve the raw JSON answer from the API, without re-loading the objects from the database, you can use:
|
291
|
+
|
292
|
+
```ruby
|
293
|
+
json_answer = Contact.raw_search("jon doe")
|
294
|
+
p json_answer
|
295
|
+
p json_answer['hits']
|
296
|
+
p json_answer['facets']
|
297
|
+
```
|
298
|
+
|
299
|
+
Search parameters can be specified either through the index's [settings](https://github.com/algolia/algoliasearch-client-ruby#index-settings-parameters) statically in your model or dynamically at search time specifying [search parameters](https://github.com/algolia/algoliasearch-client-ruby#search) as second argument of the `search` method:
|
300
|
+
|
301
|
+
```ruby
|
302
|
+
class Contact < ActiveRecord::Base
|
303
|
+
include AlgoliaSearch
|
304
|
+
|
305
|
+
algoliasearch do
|
306
|
+
attribute :first_name, :last_name, :email
|
307
|
+
|
308
|
+
# default search parameters stored in the index settings
|
309
|
+
minWordSizefor1Typo 4
|
310
|
+
minWordSizefor2Typos 8
|
311
|
+
hitsPerPage 42
|
312
|
+
end
|
313
|
+
end
|
314
|
+
```
|
315
|
+
|
316
|
+
```ruby
|
317
|
+
# dynamical search parameters
|
318
|
+
p Contact.raw_search('jon doe', { hitsPerPage: 5, page: 2 })
|
319
|
+
```
|
320
|
+
|
321
|
+
## Backend Pagination
|
202
322
|
|
203
323
|
Even if we **highly recommend to perform all search (and therefore pagination) operations from your frontend using JavaScript**, we support both [will_paginate](https://github.com/mislav/will_paginate) and [kaminari](https://github.com/amatsuda/kaminari) as pagination backend.
|
204
324
|
|
@@ -222,21 +342,129 @@ Then, as soon as you use the `search` method, the returning results will be a pa
|
|
222
342
|
<%= paginate @results %>
|
223
343
|
```
|
224
344
|
|
225
|
-
|
345
|
+
## Tags
|
226
346
|
|
227
|
-
|
347
|
+
Use the <code>tags</code> method to add tags to your record:
|
228
348
|
|
229
349
|
```ruby
|
230
|
-
Contact
|
350
|
+
class Contact < ActiveRecord::Base
|
351
|
+
include AlgoliaSearch
|
231
352
|
|
232
|
-
|
353
|
+
algoliasearch do
|
354
|
+
tags ['trusted']
|
355
|
+
end
|
356
|
+
end
|
233
357
|
```
|
234
358
|
|
235
|
-
|
359
|
+
or using dynamical values:
|
236
360
|
|
237
|
-
|
361
|
+
```ruby
|
362
|
+
class Contact < ActiveRecord::Base
|
363
|
+
include AlgoliaSearch
|
238
364
|
|
239
|
-
|
365
|
+
algoliasearch do
|
366
|
+
tags do
|
367
|
+
[first_name.blank? || last_name.blank? ? 'partial' : 'full', has_valid_email? ? 'valid_email' : 'invalid_email']
|
368
|
+
end
|
369
|
+
end
|
370
|
+
end
|
371
|
+
```
|
372
|
+
|
373
|
+
At query time, specify <code>{ tagFilters: 'tagvalue' }</code> or <code>{ tagFilters: ['tagvalue1', 'tagvalue2'] }</code> as search parameters to restrict the result set to specific tags.
|
374
|
+
|
375
|
+
## Faceting
|
376
|
+
|
377
|
+
Facets can be retrieved calling the extra `facets` method of the search answer.
|
378
|
+
|
379
|
+
```ruby
|
380
|
+
class Contact < ActiveRecord::Base
|
381
|
+
include AlgoliaSearch
|
382
|
+
|
383
|
+
algoliasearch do
|
384
|
+
# [...]
|
385
|
+
|
386
|
+
# specify the list of attributes available for faceting
|
387
|
+
attributesForFaceting [:company, :zip_code]
|
388
|
+
end
|
389
|
+
end
|
390
|
+
```
|
391
|
+
|
392
|
+
```ruby
|
393
|
+
hits = Contact.search('jon doe', { facets: '*' })
|
394
|
+
p hits # ORM-compliant array of objects
|
395
|
+
p hits.facets # extra method added to retrieve facets
|
396
|
+
p hits.facets['company'] # facet values+count of facet 'company'
|
397
|
+
p hits.facets['zip_code'] # facet values+count of facet 'zip_code'
|
398
|
+
```
|
399
|
+
|
400
|
+
```ruby
|
401
|
+
raw_json = Contact.raw_search('jon doe', { facets: '*' })
|
402
|
+
p raw_json['facets']
|
403
|
+
```
|
404
|
+
|
405
|
+
## Faceted search
|
406
|
+
|
407
|
+
You can also search for facet values.
|
408
|
+
|
409
|
+
```ruby
|
410
|
+
Product.search_for_facet_values('category', 'Headphones') # Array of {value, highlighted, count}
|
411
|
+
```
|
412
|
+
|
413
|
+
This method can also take any parameter a query can take.
|
414
|
+
This will adjust the search to only hits which would have matched the query.
|
415
|
+
|
416
|
+
```ruby
|
417
|
+
# Only sends back the categories containing red Apple products (and only counts those)
|
418
|
+
Product.search_for_facet_values('category', 'phone', {
|
419
|
+
query: 'red',
|
420
|
+
filters: 'brand:Apple'
|
421
|
+
}) # Array of phone categories linked to red Apple products
|
422
|
+
```
|
423
|
+
|
424
|
+
## Group by
|
425
|
+
|
426
|
+
More info on distinct for grouping can be found
|
427
|
+
[here](https://www.algolia.com/doc/guides/managing-results/refine-results/grouping/).
|
428
|
+
|
429
|
+
```ruby
|
430
|
+
class Contact < ActiveRecord::Base
|
431
|
+
include AlgoliaSearch
|
432
|
+
|
433
|
+
algoliasearch do
|
434
|
+
# [...]
|
435
|
+
|
436
|
+
# specify the attribute to be used for distinguishing the records
|
437
|
+
# in this case the records will be grouped by company
|
438
|
+
attributeForDistinct "company"
|
439
|
+
end
|
440
|
+
end
|
441
|
+
```
|
442
|
+
|
443
|
+
## Geo-Search
|
444
|
+
|
445
|
+
Use the <code>geoloc</code> method to localize your record:
|
446
|
+
|
447
|
+
```ruby
|
448
|
+
class Contact < ActiveRecord::Base
|
449
|
+
include AlgoliaSearch
|
450
|
+
|
451
|
+
algoliasearch do
|
452
|
+
geoloc :lat_attr, :lng_attr
|
453
|
+
end
|
454
|
+
end
|
455
|
+
```
|
456
|
+
|
457
|
+
At query time, specify <code>{ aroundLatLng: "37.33, -121.89", aroundRadius: 50000 }</code> as search parameters to restrict the result set to 50KM around San Jose.
|
458
|
+
|
459
|
+
|
460
|
+
|
461
|
+
# Options
|
462
|
+
|
463
|
+
|
464
|
+
|
465
|
+
## Auto-indexing & asynchronism
|
466
|
+
|
467
|
+
Each time a record is saved, it will be *asynchronously* indexed. On the other hand, each time a record is destroyed, it will be - asynchronously - removed from the index. That means that a network call with the ADD/DELETE operation is sent **synchronously** to the Algolia API but then the engine will **asynchronously** process the operation (so if you do a search just after, the results may not reflect it yet).
|
240
468
|
|
241
469
|
You can disable auto-indexing and auto-removing setting the following options:
|
242
470
|
|
@@ -250,7 +478,7 @@ class Contact < ActiveRecord::Base
|
|
250
478
|
end
|
251
479
|
```
|
252
480
|
|
253
|
-
|
481
|
+
### Temporary disable auto-indexing
|
254
482
|
|
255
483
|
You can temporary disable auto-indexing using the <code>without_auto_index</code> scope. This is often used for performance reason.
|
256
484
|
|
@@ -262,7 +490,7 @@ end
|
|
262
490
|
Contact.reindex! # will use batch operations
|
263
491
|
```
|
264
492
|
|
265
|
-
|
493
|
+
### Queues & background jobs
|
266
494
|
|
267
495
|
You can configure the auto-indexing & auto-removal process to use a queue to perform those operations in background. ActiveJob (Rails >=4.2) queues are used by default but you can define your own queuing mechanism:
|
268
496
|
|
@@ -276,7 +504,7 @@ class Contact < ActiveRecord::Base
|
|
276
504
|
end
|
277
505
|
```
|
278
506
|
|
279
|
-
|
507
|
+
### Things to Consider
|
280
508
|
|
281
509
|
If you are performing updates & deletions in the background then a record deletion can be committed to your database prior
|
282
510
|
to the job actually executing. Thus if you were to load the record to remove it from the database than your ActiveRecord#find will fail with a RecordNotFound.
|
@@ -300,7 +528,7 @@ class MySidekiqWorker
|
|
300
528
|
end
|
301
529
|
```
|
302
530
|
|
303
|
-
|
531
|
+
### With Sidekiq
|
304
532
|
|
305
533
|
If you're using [Sidekiq](https://github.com/mperham/sidekiq):
|
306
534
|
|
@@ -319,13 +547,21 @@ end
|
|
319
547
|
|
320
548
|
class MySidekiqWorker
|
321
549
|
def perform(id, remove)
|
322
|
-
|
323
|
-
|
550
|
+
if remove
|
551
|
+
# the record has likely already been removed from your database so we cannot
|
552
|
+
# use ActiveRecord#find to load it
|
553
|
+
index = Algolia::Index.new("index_name")
|
554
|
+
index.delete_object(id)
|
555
|
+
else
|
556
|
+
# the record should be present
|
557
|
+
c = Contact.find(id)
|
558
|
+
c.index!
|
559
|
+
end
|
324
560
|
end
|
325
561
|
end
|
326
562
|
```
|
327
563
|
|
328
|
-
|
564
|
+
### With DelayedJob
|
329
565
|
|
330
566
|
If you're using [delayed_job](https://github.com/collectiveidea/delayed_job):
|
331
567
|
|
@@ -348,7 +584,7 @@ end
|
|
348
584
|
|
349
585
|
```
|
350
586
|
|
351
|
-
|
587
|
+
### Synchronism & testing
|
352
588
|
|
353
589
|
You can force indexing and removing to be synchronous (in that case the gem will call the `wait_task` method to ensure the operation has been taken into account once the method returns) by setting the following option: (this is **NOT** recommended, except for testing purpose)
|
354
590
|
|
@@ -362,22 +598,7 @@ class Contact < ActiveRecord::Base
|
|
362
598
|
end
|
363
599
|
```
|
364
600
|
|
365
|
-
|
366
|
-
|
367
|
-
You can disable exceptions that could be raised while trying to reach Algolia's API by using the `raise_on_failure` option:
|
368
|
-
|
369
|
-
```ruby
|
370
|
-
class Contact < ActiveRecord::Base
|
371
|
-
include AlgoliaSearch
|
372
|
-
|
373
|
-
# only raise exceptions in development env
|
374
|
-
algoliasearch raise_on_failure: Rails.env.development? do
|
375
|
-
attribute :first_name, :last_name, :email
|
376
|
-
end
|
377
|
-
end
|
378
|
-
```
|
379
|
-
|
380
|
-
### Custom index name
|
601
|
+
## Custom index name
|
381
602
|
|
382
603
|
By default, the index name will be the class name, e.g. "Contact". You can customize the index name by using the `index_name` option:
|
383
604
|
|
@@ -391,7 +612,7 @@ class Contact < ActiveRecord::Base
|
|
391
612
|
end
|
392
613
|
```
|
393
614
|
|
394
|
-
|
615
|
+
## Per-environment indices
|
395
616
|
|
396
617
|
You can suffix the index name with the current Rails environment using the following option:
|
397
618
|
|
@@ -405,7 +626,7 @@ class Contact < ActiveRecord::Base
|
|
405
626
|
end
|
406
627
|
```
|
407
628
|
|
408
|
-
|
629
|
+
## Custom attribute definition
|
409
630
|
|
410
631
|
You can use a block to specify a complex attribute value
|
411
632
|
|
@@ -446,7 +667,9 @@ class Contact < ActiveRecord::Base
|
|
446
667
|
end
|
447
668
|
```
|
448
669
|
|
449
|
-
|
670
|
+
## Nested objects/relations
|
671
|
+
|
672
|
+
### Defining the relationship
|
450
673
|
|
451
674
|
You can easily embed nested objects defining an extra attribute returning any JSON-compliant object (an array or a hash or a combination of both).
|
452
675
|
|
@@ -473,7 +696,83 @@ class Profile < ActiveRecord::Base
|
|
473
696
|
end
|
474
697
|
```
|
475
698
|
|
476
|
-
###
|
699
|
+
### Propagating the change from a nested child
|
700
|
+
|
701
|
+
#### With ActiveRecord
|
702
|
+
|
703
|
+
With ActiveRecord, we'll be using `touch` and `after_touch` to achieve this.
|
704
|
+
|
705
|
+
```ruby
|
706
|
+
# app/models/app.rb
|
707
|
+
class App < ApplicationRecord
|
708
|
+
include AlgoliaSearch
|
709
|
+
|
710
|
+
belongs_to :author, class_name: :User
|
711
|
+
after_touch :index!
|
712
|
+
|
713
|
+
algoliasearch do
|
714
|
+
attribute :title
|
715
|
+
attribute :author do
|
716
|
+
author.as_json
|
717
|
+
end
|
718
|
+
end
|
719
|
+
end
|
720
|
+
|
721
|
+
# app/models/user.rb
|
722
|
+
class User < ApplicationRecord
|
723
|
+
# If your association uses belongs_to
|
724
|
+
# - use `touch: true`
|
725
|
+
# - do not define an `after_save` hook
|
726
|
+
has_many :apps, foreign_key: :author_id
|
727
|
+
|
728
|
+
after_save { apps.each(&:touch) }
|
729
|
+
end
|
730
|
+
```
|
731
|
+
|
732
|
+
#### With Sequel
|
733
|
+
|
734
|
+
With Sequel, you can use the `touch` plugin to propagate the changes:
|
735
|
+
|
736
|
+
```ruby
|
737
|
+
# app/models/app.rb
|
738
|
+
class App < Sequel::Model
|
739
|
+
include AlgoliaSearch
|
740
|
+
|
741
|
+
many_to_one :author, class: :User
|
742
|
+
|
743
|
+
plugin :timestamps
|
744
|
+
plugin :touch
|
745
|
+
|
746
|
+
algoliasearch do
|
747
|
+
attribute :title
|
748
|
+
attribute :author do
|
749
|
+
author.to_hash
|
750
|
+
end
|
751
|
+
end
|
752
|
+
end
|
753
|
+
|
754
|
+
# app/models/user.rb
|
755
|
+
class User < Sequel::Model
|
756
|
+
one_to_many :apps, key: :author_id
|
757
|
+
|
758
|
+
plugin :timestamps
|
759
|
+
# Can't use the associations since it won't trigger the after_save
|
760
|
+
plugin :touch
|
761
|
+
|
762
|
+
# Define the associations that need to be touched here
|
763
|
+
# Less performant, but allows for the after_save hook to trigger
|
764
|
+
def touch_associations
|
765
|
+
apps.map(&:touch)
|
766
|
+
end
|
767
|
+
|
768
|
+
def touch
|
769
|
+
super
|
770
|
+
touch_associations
|
771
|
+
end
|
772
|
+
end
|
773
|
+
```
|
774
|
+
|
775
|
+
## Custom `objectID`
|
477
776
|
|
478
777
|
By default, the `objectID` is based on your record's `id`. You can change this behavior specifying the `:id` option (be sure to use a uniq field).
|
479
778
|
|
@@ -486,7 +785,7 @@ class UniqUser < ActiveRecord::Base
|
|
486
785
|
end
|
487
786
|
```
|
488
787
|
|
489
|
-
|
788
|
+
## Restrict indexing to a subset of your data
|
490
789
|
|
491
790
|
You can add constraints controlling if a record must be indexed by using options the `:if` or `:unless` options.
|
492
791
|
|
@@ -528,7 +827,6 @@ class Contact < ActiveRecord::Base
|
|
528
827
|
end
|
529
828
|
```
|
530
829
|
|
531
|
-
|
532
830
|
You can index a subset of your records using either:
|
533
831
|
|
534
832
|
```ruby
|
@@ -542,7 +840,7 @@ or
|
|
542
840
|
MyModel.index_objects MyModel.limit(5)
|
543
841
|
```
|
544
842
|
|
545
|
-
|
843
|
+
## Sanitizer
|
546
844
|
|
547
845
|
You can sanitize all your attributes using the `sanitize` option. It will strip all HTML tags from your attributes.
|
548
846
|
|
@@ -563,8 +861,7 @@ If you're using Rails 4.2+, you also need to depend on `rails-html-sanitizer`:
|
|
563
861
|
gem 'rails-html-sanitizer'
|
564
862
|
```
|
565
863
|
|
566
|
-
|
567
|
-
### UTF-8 Encoding
|
864
|
+
## UTF-8 Encoding
|
568
865
|
|
569
866
|
You can force the UTF-8 encoding of all your attributes using the `force_utf8_encoding` option:
|
570
867
|
|
@@ -581,8 +878,22 @@ end
|
|
581
878
|
|
582
879
|
***Notes:*** This option is not compatible with Ruby 1.8
|
583
880
|
|
881
|
+
## Exceptions
|
584
882
|
|
585
|
-
|
883
|
+
You can disable exceptions that could be raised while trying to reach Algolia's API by using the `raise_on_failure` option:
|
884
|
+
|
885
|
+
```ruby
|
886
|
+
class Contact < ActiveRecord::Base
|
887
|
+
include AlgoliaSearch
|
888
|
+
|
889
|
+
# only raise exceptions in development env
|
890
|
+
algoliasearch raise_on_failure: Rails.env.development? do
|
891
|
+
attribute :first_name, :last_name, :email
|
892
|
+
end
|
893
|
+
end
|
894
|
+
```
|
895
|
+
|
896
|
+
## Configuration example
|
586
897
|
|
587
898
|
Here is a real-word configuration example (from [HN Search](https://github.com/algolia/hn-search)):
|
588
899
|
|
@@ -601,7 +912,7 @@ class Item < ActiveRecord::Base
|
|
601
912
|
|
602
913
|
# `title` is more important than `{story,comment}_text`, `{story,comment}_text` more than `url`, `url` more than `author`
|
603
914
|
# btw, do not take into account position in most fields to avoid first word match boost
|
604
|
-
|
915
|
+
searchableAttributes ['unordered(title)', 'unordered(story_text)', 'unordered(comment_text)', 'unordered(url)', 'author']
|
605
916
|
|
606
917
|
# tags used for filtering
|
607
918
|
tags do
|
@@ -639,9 +950,13 @@ class Item < ActiveRecord::Base
|
|
639
950
|
end
|
640
951
|
```
|
641
952
|
|
642
|
-
## Indexing
|
643
953
|
|
644
|
-
|
954
|
+
|
955
|
+
# Indices
|
956
|
+
|
957
|
+
|
958
|
+
|
959
|
+
## Manual indexing
|
645
960
|
|
646
961
|
You can trigger indexing using the <code>index!</code> instance method.
|
647
962
|
|
@@ -650,7 +965,7 @@ c = Contact.create!(params[:contact])
|
|
650
965
|
c.index!
|
651
966
|
```
|
652
967
|
|
653
|
-
|
968
|
+
## Manual removal
|
654
969
|
|
655
970
|
And trigger index removing using the <code>remove_from_index!</code> instance method.
|
656
971
|
|
@@ -659,13 +974,13 @@ c.remove_from_index!
|
|
659
974
|
c.destroy
|
660
975
|
```
|
661
976
|
|
662
|
-
|
977
|
+
## Reindexing
|
663
978
|
|
664
979
|
The gem provides 2 ways to reindex all your objects:
|
665
980
|
|
666
|
-
|
981
|
+
### Atomical reindexing
|
667
982
|
|
668
|
-
To reindex all your records (taking into account the deleted objects), the `reindex` class method
|
983
|
+
To reindex all your records (taking into account the deleted objects), the `reindex` class method indices all your objects to a temporary index called `<INDEX_NAME>.tmp` and moves the temporary index to the final one once everything is indexed (atomically). This is the safest way to reindex all your content.
|
669
984
|
|
670
985
|
```ruby
|
671
986
|
Contact.reindex
|
@@ -673,7 +988,9 @@ Contact.reindex
|
|
673
988
|
|
674
989
|
**Notes**: if you're using an index-specific API key, ensure you're allowing both `<INDEX_NAME>` and `<INDEX_NAME>.tmp`.
|
675
990
|
|
676
|
-
|
991
|
+
**Warning:** You should not use such an atomic reindexing operation while scoping/filtering the model because this operation **replaces the entire index**, keeping the filtered objects only. ie: Don't do `MyModel.where(...).reindex` but do `MyModel.where(...).reindex!` (with the trailing `!`)!!!
|
992
|
+
|
993
|
+
### Regular reindexing
|
677
994
|
|
678
995
|
To reindex all your objects in place (without temporary index and therefore without deleting removed objects), use the `reindex!` class method:
|
679
996
|
|
@@ -681,7 +998,7 @@ To reindex all your objects in place (without temporary index and therefore with
|
|
681
998
|
Contact.reindex!
|
682
999
|
```
|
683
1000
|
|
684
|
-
|
1001
|
+
## Clearing an index
|
685
1002
|
|
686
1003
|
To clear an index, use the <code>clear_index!</code> class method:
|
687
1004
|
|
@@ -689,7 +1006,7 @@ To clear an index, use the <code>clear_index!</code> class method:
|
|
689
1006
|
Contact.clear_index!
|
690
1007
|
```
|
691
1008
|
|
692
|
-
|
1009
|
+
## Using the underlying index
|
693
1010
|
|
694
1011
|
You can access the underlying `index` object by calling the `index` class method:
|
695
1012
|
|
@@ -698,11 +1015,10 @@ index = Contact.index
|
|
698
1015
|
# index.get_settings, index.partial_update_object, ...
|
699
1016
|
```
|
700
1017
|
|
701
|
-
##
|
702
|
-
|
703
|
-
### Master/slave
|
1018
|
+
## Primary/replica
|
704
1019
|
|
705
|
-
You can define
|
1020
|
+
You can define replica indices using the <code>add_replica</code> method.
|
1021
|
+
Use `inherit: true` on the replica block if you want it to inherit from the primary settings.
|
706
1022
|
|
707
1023
|
```ruby
|
708
1024
|
class Book < ActiveRecord::Base
|
@@ -711,31 +1027,31 @@ class Book < ActiveRecord::Base
|
|
711
1027
|
include AlgoliaSearch
|
712
1028
|
|
713
1029
|
algoliasearch per_environment: true do
|
714
|
-
|
1030
|
+
searchableAttributes [:name, :author, :editor]
|
715
1031
|
|
716
|
-
# define a
|
717
|
-
|
718
|
-
|
1032
|
+
# define a replica index to search by `author` only
|
1033
|
+
add_replica 'Book_by_author', per_environment: true do
|
1034
|
+
searchableAttributes [:author]
|
719
1035
|
end
|
720
1036
|
|
721
|
-
# define a
|
722
|
-
|
723
|
-
|
1037
|
+
# define a replica index with custom ordering but same settings than the main block
|
1038
|
+
add_replica 'Book_custom_order', inherit: true, per_environment: true do
|
1039
|
+
customRanking ['asc(rank)']
|
724
1040
|
end
|
725
1041
|
end
|
726
1042
|
|
727
1043
|
end
|
728
1044
|
```
|
729
1045
|
|
730
|
-
To search using a
|
1046
|
+
To search using a replica, use the following code:
|
731
1047
|
|
732
1048
|
```ruby
|
733
|
-
Book.raw_search 'foo bar',
|
1049
|
+
Book.raw_search 'foo bar', replica: 'Book_by_editor'
|
734
1050
|
# or
|
735
|
-
Book.search 'foo bar',
|
1051
|
+
Book.search 'foo bar', replica: 'Book_by_editor'
|
736
1052
|
```
|
737
1053
|
|
738
|
-
|
1054
|
+
## Share a single index
|
739
1055
|
|
740
1056
|
It can make sense to share an index between several models. In order to implement that, you'll need to ensure you don't have any conflict with the `objectID` of the underlying models.
|
741
1057
|
|
@@ -773,9 +1089,9 @@ end
|
|
773
1089
|
|
774
1090
|
***Notes:*** If you target a single index from several models, you must never use `MyModel.reindex` and only use `MyModel.reindex!`. The `reindex` method uses a temporary index to perform an atomic reindexing: if you use it, the resulting index will only contain records for the current model because it will not reindex the others.
|
775
1091
|
|
776
|
-
|
1092
|
+
## Target multiple indices
|
777
1093
|
|
778
|
-
You can index a record in several
|
1094
|
+
You can index a record in several indices using the <code>add_index</code> method:
|
779
1095
|
|
780
1096
|
```ruby
|
781
1097
|
class Book < ActiveRecord::Base
|
@@ -788,7 +1104,7 @@ class Book < ActiveRecord::Base
|
|
788
1104
|
|
789
1105
|
# store all books in index 'SECURED_INDEX_NAME'
|
790
1106
|
algoliasearch index_name: SECURED_INDEX_NAME do
|
791
|
-
|
1107
|
+
searchableAttributes [:name, :author]
|
792
1108
|
# convert security to tags
|
793
1109
|
tags do
|
794
1110
|
[released ? 'public' : 'private', premium ? 'premium' : 'standard']
|
@@ -796,7 +1112,7 @@ class Book < ActiveRecord::Base
|
|
796
1112
|
|
797
1113
|
# store all 'public' (released and not premium) books in index 'PUBLIC_INDEX_NAME'
|
798
1114
|
add_index PUBLIC_INDEX_NAME, if: :public? do
|
799
|
-
|
1115
|
+
searchableAttributes [:name, :author]
|
800
1116
|
end
|
801
1117
|
end
|
802
1118
|
|
@@ -816,198 +1132,15 @@ Book.raw_search 'foo bar', index: 'Book_by_editor'
|
|
816
1132
|
Book.search 'foo bar', index: 'Book_by_editor'
|
817
1133
|
```
|
818
1134
|
|
819
|
-
## Features
|
820
1135
|
|
821
|
-
### Tags
|
822
1136
|
|
823
|
-
|
1137
|
+
# Testing
|
824
1138
|
|
825
|
-
```ruby
|
826
|
-
class Contact < ActiveRecord::Base
|
827
|
-
include AlgoliaSearch
|
828
1139
|
|
829
|
-
algoliasearch do
|
830
|
-
tags ['trusted']
|
831
|
-
end
|
832
|
-
end
|
833
|
-
```
|
834
|
-
|
835
|
-
or using dynamical values:
|
836
|
-
|
837
|
-
```ruby
|
838
|
-
class Contact < ActiveRecord::Base
|
839
|
-
include AlgoliaSearch
|
840
|
-
|
841
|
-
algoliasearch do
|
842
|
-
tags do
|
843
|
-
[first_name.blank? || last_name.blank? ? 'partial' : 'full', has_valid_email? ? 'valid_email' : 'invalid_email']
|
844
|
-
end
|
845
|
-
end
|
846
|
-
end
|
847
|
-
```
|
848
|
-
|
849
|
-
At query time, specify <code>{ tagFilters: 'tagvalue' }</code> or <code>{ tagFilters: ['tagvalue1', 'tagvalue2'] }</code> as search parameters to restrict the result set to specific tags.
|
850
|
-
|
851
|
-
### Search
|
852
|
-
|
853
|
-
***Notes:*** We recommend the usage of our [JavaScript API Client](https://github.com/algolia/algoliasearch-client-js) to perform queries directly from the end-user browser without going through your server.
|
854
|
-
|
855
|
-
A search returns ORM-compliant objects reloading them from your database. We recommend the usage of our [JavaScript API Client](https://github.com/algolia/algoliasearch-client-js) to perform queries to decrease the overall latency and offload your servers.
|
856
|
-
|
857
|
-
|
858
|
-
```ruby
|
859
|
-
hits = Contact.search("jon doe")
|
860
|
-
p hits
|
861
|
-
p hits.raw_answer # to get the original JSON raw answer
|
862
|
-
```
|
863
|
-
|
864
|
-
A `highlight_result` attribute is added to each ORM object:
|
865
|
-
|
866
|
-
```ruby
|
867
|
-
hits[0].highlight_result['first_name']['value']
|
868
|
-
```
|
869
1140
|
|
870
|
-
|
1141
|
+
## Notes
|
871
1142
|
|
872
|
-
|
873
|
-
json_answer = Contact.raw_search("jon doe")
|
874
|
-
p json_answer
|
875
|
-
p json_answer['hits']
|
876
|
-
p json_answer['facets']
|
877
|
-
```
|
878
|
-
|
879
|
-
Search parameters can be specified either through the index's [settings](https://github.com/algolia/algoliasearch-client-ruby#index-settings-parameters) statically in your model or dynamically at search time specifying [search parameters](https://github.com/algolia/algoliasearch-client-ruby#search) as second argument of the `search` method:
|
880
|
-
|
881
|
-
```ruby
|
882
|
-
class Contact < ActiveRecord::Base
|
883
|
-
include AlgoliaSearch
|
884
|
-
|
885
|
-
algoliasearch do
|
886
|
-
attribute :first_name, :last_name, :email
|
887
|
-
|
888
|
-
# default search parameters stored in the index settings
|
889
|
-
minWordSizeForApprox1 4
|
890
|
-
minWordSizeForApprox2 8
|
891
|
-
hitsPerPage 42
|
892
|
-
end
|
893
|
-
end
|
894
|
-
```
|
895
|
-
|
896
|
-
|
897
|
-
```ruby
|
898
|
-
# dynamical search parameters
|
899
|
-
p Contact.raw_search("jon doe", { :hitsPerPage => 5, :page => 2 })
|
900
|
-
```
|
901
|
-
|
902
|
-
### Faceting
|
903
|
-
|
904
|
-
Facets can be retrieved calling the extra `facets` method of the search answer.
|
905
|
-
|
906
|
-
```ruby
|
907
|
-
class Contact < ActiveRecord::Base
|
908
|
-
include AlgoliaSearch
|
909
|
-
|
910
|
-
algoliasearch do
|
911
|
-
# [...]
|
912
|
-
|
913
|
-
# specify the list of attributes available for faceting
|
914
|
-
attributesForFaceting [:company, :zip_code]
|
915
|
-
end
|
916
|
-
end
|
917
|
-
```
|
918
|
-
|
919
|
-
|
920
|
-
```ruby
|
921
|
-
hits = Contact.search("jon doe", { :facets => '*' })
|
922
|
-
p hits # ORM-compliant array of objects
|
923
|
-
p hits.facets # extra method added to retrieve facets
|
924
|
-
p hits.facets['company'] # facet values+count of facet 'company'
|
925
|
-
p hits.facets['zip_code'] # facet values+count of facet 'zip_code'
|
926
|
-
```
|
927
|
-
|
928
|
-
|
929
|
-
```ruby
|
930
|
-
raw_json = Contact.raw_search("jon doe", { :facets => '*' })
|
931
|
-
p raw_json['facets']
|
932
|
-
```
|
933
|
-
|
934
|
-
### Facet search
|
935
|
-
|
936
|
-
You can also search for facet values.
|
937
|
-
|
938
|
-
```ruby
|
939
|
-
Product.search_for_facet_values('category', 'Headphones') # Array of {value, highlighted, count}
|
940
|
-
```
|
941
|
-
|
942
|
-
This method can also take any parameter a query can take.
|
943
|
-
This will adjust the search to only hits which would have matched the query.
|
944
|
-
|
945
|
-
```ruby
|
946
|
-
# Only sends back the categories containing red Apple products (and only counts those)
|
947
|
-
Product.search_for_facet_values('category', 'phone', {
|
948
|
-
query: 'red',
|
949
|
-
filters: 'brand:Apple'
|
950
|
-
}) # Array of phone categories linked to red Apple products
|
951
|
-
```
|
952
|
-
|
953
|
-
### Group by
|
954
|
-
|
955
|
-
More info on distinct for grouping can be found
|
956
|
-
[here](https://www.algolia.com/doc/guides/search/distinct#distinct-for-grouping).
|
957
|
-
|
958
|
-
```ruby
|
959
|
-
class Contact < ActiveRecord::Base
|
960
|
-
include AlgoliaSearch
|
961
|
-
|
962
|
-
algoliasearch do
|
963
|
-
# [...]
|
964
|
-
|
965
|
-
# specify the attribute to be used for distinguishing the records
|
966
|
-
# in this case the records will be grouped by company
|
967
|
-
attributeForDistinct "company"
|
968
|
-
end
|
969
|
-
end
|
970
|
-
```
|
971
|
-
|
972
|
-
### Geo-Search
|
973
|
-
|
974
|
-
Use the <code>geoloc</code> method to localize your record:
|
975
|
-
|
976
|
-
```ruby
|
977
|
-
class Contact < ActiveRecord::Base
|
978
|
-
include AlgoliaSearch
|
979
|
-
|
980
|
-
algoliasearch do
|
981
|
-
geoloc :lat_attr, :lng_attr
|
982
|
-
end
|
983
|
-
end
|
984
|
-
```
|
985
|
-
|
986
|
-
At query time, specify <code>{ aroundLatLng: "37.33, -121.89", aroundRadius: 50000 }</code> as search parameters to restrict the result set to 50KM around San Jose.
|
987
|
-
|
988
|
-
### Caveats
|
989
|
-
|
990
|
-
This gem makes intensive use of Rails' callbacks to trigger the indexing tasks. If you're using methods bypassing `after_validation`, `before_save` or `after_commit` callbacks, it will not index your changes. For example: `update_attribute` doesn't perform validations checks, to perform validations when updating use `update_attributes`.
|
991
|
-
|
992
|
-
### Timeouts
|
993
|
-
|
994
|
-
You can configure a bunch of timeout threshold by setting the following options at initialization time:
|
995
|
-
|
996
|
-
```ruby
|
997
|
-
AlgoliaSearch.configuration = {
|
998
|
-
application_id: 'YourApplicationID',
|
999
|
-
api_key: 'YourAPIKey'
|
1000
|
-
connect_timeout: 2,
|
1001
|
-
receive_timeout: 30,
|
1002
|
-
send_timeout: 30,
|
1003
|
-
batch_timeout: 120,
|
1004
|
-
search_timeout: 5
|
1005
|
-
}
|
1006
|
-
```
|
1007
|
-
|
1008
|
-
### Note on testing
|
1009
|
-
|
1010
|
-
To run the specs, please set the <code>ALGOLIA_APPLICATION_ID</code> and <code>ALGOLIA_API_KEY</code> environment variables. Since the tests are creating and removing indexes, DO NOT use your production account.
|
1143
|
+
To run the specs, please set the <code>ALGOLIA_APPLICATION_ID</code> and <code>ALGOLIA_API_KEY</code> environment variables. Since the tests are creating and removing indices, DO NOT use your production account.
|
1011
1144
|
|
1012
1145
|
You may want to disable all indexing (add, update & delete operations) API calls, you can set the `disable_indexing` option:
|
1013
1146
|
|
@@ -1015,14 +1148,14 @@ You may want to disable all indexing (add, update & delete operations) API calls
|
|
1015
1148
|
class User < ActiveRecord::Base
|
1016
1149
|
include AlgoliaSearch
|
1017
1150
|
|
1018
|
-
algoliasearch :
|
1151
|
+
algoliasearch per_environment: true, disable_indexing: Rails.env.test? do
|
1019
1152
|
end
|
1020
1153
|
end
|
1021
1154
|
|
1022
1155
|
class User < ActiveRecord::Base
|
1023
1156
|
include AlgoliaSearch
|
1024
1157
|
|
1025
|
-
algoliasearch :
|
1158
|
+
algoliasearch per_environment: true, disable_indexing: Proc.new { Rails.env.test? || more_complex_condition } do
|
1026
1159
|
end
|
1027
1160
|
end
|
1028
1161
|
```
|
@@ -1050,3 +1183,12 @@ describe 'With a mocked client' do
|
|
1050
1183
|
end
|
1051
1184
|
```
|
1052
1185
|
|
1186
|
+
|
1187
|
+
## ❓ Troubleshooting
|
1188
|
+
|
1189
|
+
Encountering an issue? Before reaching out to support, we recommend heading to our [FAQ](https://www.algolia.com/doc/api-client/troubleshooting/faq/ruby/) where you will find answers for the most common issues and gotchas with the client.
|
1190
|
+
|
1191
|
+
## Use the Dockerfile
|
1192
|
+
|
1193
|
+
If you want to contribute to this project without installing all its dependencies, you can use our Docker image. Please check our [dedicated guide](DOCKER_README.MD) to learn more.
|
1194
|
+
|