algoliasearch 1.6.1 → 1.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ef471816ed6c3a24ae2e7234eeb60170759f7da4
4
- data.tar.gz: 5f01f60e53337d61d8e0706df21bb1b1214d32b0
3
+ metadata.gz: 09439a03773ded1c14b3085d75beca0fcd8ad5ea
4
+ data.tar.gz: 0afd459775b461e96b952540f2889a54c7b8a9c6
5
5
  SHA512:
6
- metadata.gz: 010fdf10d52c1079b0dee5992fe5c34eadd854d65195af1b1737da6dcacc77bdb99c47525a35bcddbaf6bc996dd66fc2bae2d1bc3f562e6168b9621dad7c54d2
7
- data.tar.gz: 1e76b4c1fb64212de61999489c107d398fb47578a3bb13b6289b89d38cee086144f7881b49a9ab53f9a67ab137d20f0da21fa1eb4a6b15a07e4e552f7e5b6ddc
6
+ metadata.gz: b1cb21a4b0382bf44a5319d4060a816300c53a14c43db82b5e21b89a607650b6f9bbc3e0bf02c5227c2e20488333593d630e4ac5834c0f4a520c346c5aa0c14a
7
+ data.tar.gz: 65e765e1557b807f380f010c1ac2548a804e9fae494003dbb8b151bc187dd4ff9bfddff3628d8828be756ea49893b003ce5cb1b4cdee0cb91e95747f526694c3
data/ChangeLog CHANGED
@@ -1,5 +1,8 @@
1
1
  CHANGELOG
2
2
 
3
+ 2016-01-09 1.7.0
4
+ * New generate_secured_api_key embedding the filters in the resulting key
5
+
3
6
  2015-08-01 1.6.1
4
7
  * Search queries are now using POST requests
5
8
 
data/README.md CHANGED
@@ -3,11 +3,14 @@
3
3
 
4
4
 
5
5
 
6
+
6
7
  [Algolia Search](http://www.algolia.com) is a hosted full-text, numerical, and faceted search engine capable of delivering realtime results from the first keystroke.
7
8
 
8
9
  Our Ruby client lets you easily use the [Algolia Search API](https://www.algolia.com/doc/rest_api) from your backend. It wraps the [Algolia Search REST API](http://www.algolia.com/doc/rest_api).
9
10
 
10
11
 
12
+
13
+
11
14
  [![Build Status](https://travis-ci.org/algolia/algoliasearch-client-ruby.svg?branch=master)](https://travis-ci.org/algolia/algoliasearch-client-ruby) [![Gem Version](https://badge.fury.io/rb/algoliasearch.svg)](http://badge.fury.io/rb/algoliasearch) [![Code Climate](https://codeclimate.com/github/algolia/algoliasearch-client-ruby.svg)](https://codeclimate.com/github/algolia/algoliasearch-client-ruby) [![Coverage Status](https://coveralls.io/repos/algolia/algoliasearch-client-ruby/badge.png)](https://coveralls.io/r/algolia/algoliasearch-client-ruby)
12
15
 
13
16
 
@@ -22,6 +25,7 @@ Table of Contents
22
25
  1. [Online documentation](#documentation)
23
26
  1. [Tutorials](#tutorials)
24
27
 
28
+
25
29
  **Commands Reference**
26
30
 
27
31
  1. [Add a new object](#add-a-new-object-to-the-index)
@@ -51,7 +55,6 @@ To setup your project, follow these steps:
51
55
 
52
56
 
53
57
 
54
-
55
58
  1. Install AlgoliaSearch using <code>gem install algoliasearch</code>.
56
59
  2. Initialize the client with your ApplicationID and API-Key. You can find all of them on [your Algolia account](http://www.algolia.com/users/edit).
57
60
 
@@ -173,6 +176,7 @@ Check out our [tutorials](http://www.algolia.com/doc/tutorials):
173
176
 
174
177
 
175
178
 
179
+
176
180
  Commands Reference
177
181
  ==================
178
182
 
@@ -226,9 +230,9 @@ index.save_object({"firstname" => "Jimmie",
226
230
  You have many ways to update an object's attributes:
227
231
 
228
232
  1. Set the attribute value
229
- 2. Add an element to an array
233
+ 2. Add a string or number element to an array
230
234
  3. Remove an element from an array
231
- 4. Add an element to an array if it doesn't exist
235
+ 4. Add a string or number element to an array if it doesn't exist
232
236
  5. Increment an attribute
233
237
  6. Decrement an attribute
234
238
 
@@ -242,38 +246,44 @@ index.partial_update_object({"city" => "San Francisco",
242
246
  Example to add a tag:
243
247
 
244
248
  ```ruby
245
- index.partial_update_object({"_tags" => {"value" => "MyTag", "_operation": "Add"},
249
+ index.partial_update_object({"_tags" => {"value" => "MyTag", "_operation" => "Add"},
246
250
  "objectID" => "myID"})
247
251
  ```
248
252
 
249
253
  Example to remove a tag:
250
254
 
251
255
  ```ruby
252
- index.partial_update_object({"_tags" => {"value" => "MyTag", "_operation": "Remove"},
256
+ index.partial_update_object({"_tags" => {"value" => "MyTag", "_operation" => "Remove"},
253
257
  "objectID" => "myID"})
254
258
  ```
255
259
 
256
260
  Example to add a tag if it doesn't exist:
257
261
 
258
262
  ```ruby
259
- index.partial_update_object({"_tags" => {"value" => "MyTag", "_operation": "AddUnique"},
263
+ index.partial_update_object({"_tags" => {"value" => "MyTag", "_operation" => "AddUnique"},
260
264
  "objectID" => "myID"})
261
265
  ```
262
266
 
263
267
  Example to increment a numeric value:
264
268
 
265
269
  ```ruby
266
- index.partial_update_object({"price" => {"value" => 42, "_operation": "Increment"},
270
+ index.partial_update_object({"price" => {"value" => 42, "_operation" => "Increment"},
267
271
  "objectID" => "myID"})
268
272
  ```
269
273
 
274
+ Note: Here we are incrementing the value by `42`. To increment just by one, put
275
+ `value:1`.
276
+
270
277
  Example to decrement a numeric value:
271
278
 
272
279
  ```ruby
273
- index.partial_update_object({"price" => {"value" => 42, "_operation": "Decrement"},
280
+ index.partial_update_object({"price" => {"value" => 42, "_operation" => "Decrement"},
274
281
  "objectID" => "myID"})
275
282
  ```
276
283
 
284
+ Note: Here we are decrementing the value by `42`. To decrement just by one, put
285
+ `value:1`.
286
+
277
287
  Search
278
288
  -------------
279
289
 
@@ -284,6 +294,8 @@ Search
284
294
 
285
295
  To perform a search, you only need to initialize the index and perform a call to the search function.
286
296
 
297
+ The search query allows only to retrieve 1000 hits, if you need to retrieve more than 1000 hits for seo, you can use [Backup / Retrieve all index content](#backup--retrieve-of-all-index-content)
298
+
287
299
  You can use the following optional arguments:
288
300
 
289
301
  ### Query Parameters
@@ -298,7 +310,7 @@ You can use the following optional arguments:
298
310
  * **removeWordsIfNoResults**: This option is used to select a strategy in order to avoid having an empty result page. There are three different options:
299
311
  * **lastWords**: When a query does not return any results, the last word will be added as optional. The process is repeated with n-1 word, n-2 word, ... until there are results.
300
312
  * **firstWords**: When a query does not return any results, the first word will be added as optional. The process is repeated with second word, third word, ... until there are results.
301
- * **allOptional**: When a query does not return any results, a second trial will be made with all words as optional. This is equivalent to transforming the AND operand between query terms to an OR operand.
313
+ * **allOptional**: When a query does not return any results, a second trial will be made with all words as optional. This is equivalent to transforming the AND operand between query terms to an OR operand.
302
314
  * **none**: No specific processing is done when a query does not return any results (default behavior).
303
315
  * **minWordSizefor1Typo**: The minimum number of characters in a query word to accept one typo in this word.<br/>Defaults to 4.
304
316
  * **minWordSizefor2Typos**: The minimum number of characters in a query word to accept two typos in this word.<br/>Defaults to 8.
@@ -310,7 +322,9 @@ You can use the following optional arguments:
310
322
  * **strict**: Hits matching with 2 typos are not retrieved if there are some matching without typos. This option is useful if you want to avoid false positives as much as possible.
311
323
  * **allowTyposOnNumericTokens**: If set to false, disables typo tolerance on numeric tokens (numbers). Defaults to true.
312
324
  * **ignorePlural**: If set to true, plural won't be considered as a typo. For example, car and cars will be considered as equals. Defaults to false.
325
+ * **disableTypoToleranceOnAttributes** List of attributes on which you want to disable typo tolerance (must be a subset of the `attributesToIndex` index setting). Attributes are separated with a comma such as `"name,address"`. You can also use JSON string array encoding such as `encodeURIComponent("[\"name\",\"address\"]")`. By default, this list is empty.
313
326
  * **restrictSearchableAttributes** List of attributes you want to use for textual search (must be a subset of the `attributesToIndex` index setting). Attributes are separated with a comma such as `"name,address"`. You can also use JSON string array encoding such as `encodeURIComponent("[\"name\",\"address\"]")`. By default, all attributes specified in `attributesToIndex` settings are used to search.
327
+ * **removeStopWords**: Remove stop words from query before executing it. Defaults to false. Contains stop words for 41 languages (Arabic, Armenian, Basque, Bengali, Brazilian, Bulgarian, Catalan, Chinese, Czech, Danish, Dutch, English, Finnish, French, Galician, German, Greek, Hindi, Hungarian, Indonesian, Irish, Italian, Japanese, Korean, Kurdish, Latvian, Lithuanian, Marathi, Norwegian, Persian, Polish, Portugese, Romanian, Russian, Slovak, Spanish, Swedish, Thai, Turkish, Ukranian, Urdu).
314
328
  * **advancedSyntax**: Enables the advanced query syntax. Defaults to 0 (false).
315
329
  * **Phrase query**: A phrase query defines a particular sequence of terms. A phrase query is built by Algolia's query parser for words surrounded by `"`. For example, `"search engine"` will retrieve records having `search` next to `engine` only. Typo tolerance is _disabled_ on phrase queries.
316
330
  * **Prohibit operator**: The prohibit operator excludes records that contain the term after the `-` symbol. For example, `search -engine` will retrieve records containing `search` but not `engine`.
@@ -326,12 +340,12 @@ You can use the following optional arguments:
326
340
 
327
341
  #### Geo-search Parameters
328
342
 
329
- * **aroundLatLng**: Search for entries around a given latitude/longitude (specified as two floats separated by a comma).<br/>For example, `aroundLatLng=47.316669,5.016670`.<br/>You can specify the maximum distance in meters with the **aroundRadius** parameter and the precision for ranking with **aroundPrecision**. For example, if you set aroundPrecision=100, two objects that are a distance of less than 100 meters will be considered as identical for the "geo" ranking parameter).<br/>At indexing, you should specify the geo location of an object with the `_geoloc` attribute in the form `{"_geoloc":{"lat":48.853409, "lng":2.348800}}`.
330
-
331
- * **aroundLatLngViaIP**: Search for entries around a given latitude/longitude automatically computed from user IP address.<br/>For example, `aroundLatLng=47.316669,5.016670`.<br/>You can specify the maximum distance in meters with the **aroundRadius** parameter and the precision for ranking with **aroundPrecision**. For example, if you set aroundPrecision=100, two objects that are a distance of less than 100 meters will be considered as identical for the "geo" ranking parameter.<br/>At indexing, you should specify the geo location of an object with the `_geoloc` attribute in the form `{"_geoloc":{"lat":48.853409, "lng":2.348800}}`.
343
+ * **aroundLatLng**: Search for entries around a given latitude/longitude (specified as two floats separated by a comma).<br/>For example, `aroundLatLng=47.316669,5.016670`.<br/>By default the maximum distance is automatically guessed based on the density of the area but you can specify it manually in meters with the **aroundRadius** parameter. The precision for ranking can be set with **aroundPrecision** parameter. For example, if you set aroundPrecision=100, the distances will be considered by ranges of 100m, for example all distances 0 and 100m will be considered as identical for the "geo" ranking parameter.<br/>When **aroundRadius** is not set, the radius is computed automatically using the density of the area, you can retrieve the computed radius in the **automaticRadius** attribute of the answer, you can also use the **minimumAroundRadius** query parameter to specify a minimum radius in meters for the automatic computation of **aroundRadius**.<br/>At indexing, you should specify geoloc of an object with the _geoloc attribute (in the form `"_geoloc":{"lat":48.853409, "lng":2.348800}` or `"_geoloc":[{"lat":48.853409, "lng":2.348800},{"lat":48.547456, "lng":2.972075}]` if you have several geo-locations in your record).
332
344
 
345
+ * **aroundLatLngViaIP**: Search for entries around a given latitude/longitude automatically computed from user IP address.<br/>For example, `aroundLatLng=47.316669,5.016670`.<br/>You can specify the maximum distance in meters with the **aroundRadius** parameter and the precision for ranking with **aroundPrecision**. For example, if you set aroundPrecision=100, two objects that are in the range 0-99m will be considered as identic in the ranking for the "geo" ranking parameter (same for 100-199, 200-299, ... ranges).<br/>At indexing, you should specify the geo location of an object with the `_geoloc` attribute in the form `{"_geoloc":{"lat":48.853409, "lng":2.348800}}`.
333
346
 
334
- * **insideBoundingBox**: Search entries inside a given area defined by the two extreme points of a rectangle (defined by 4 floats: p1Lat,p1Lng,p2Lat,p2Lng).<br/>For example, `insideBoundingBox=47.3165,4.9665,47.3424,5.0201`).<br/>At indexing, you should specify the geo location of an object with the _geoloc attribute in the form `{"_geoloc":{"lat":48.853409, "lng":2.348800}}`.
347
+ * **insideBoundingBox**: Search entries inside a given area defined by the two extreme points of a rectangle (defined by 4 floats: p1Lat,p1Lng,p2Lat,p2Lng).<br/>For example, `insideBoundingBox=47.3165,4.9665,47.3424,5.0201`).<br/>At indexing, you should specify geoloc of an object with the _geoloc attribute (in the form `"_geoloc":{"lat":48.853409, "lng":2.348800}` or `"_geoloc":[{"lat":48.853409, "lng":2.348800},{"lat":48.547456, "lng":2.972075}]` if you have several geo-locations in your record). You can use several bounding boxes (OR) by passing more than 4 values. For example instead of having 4 values you can pass 8 to use or OR between two bounding boxes.
348
+ * **insidePolygon**: Search entries inside a given area defined by a set of points (defined by a minimum of 6 floats: p1Lat,p1Lng,p2Lat,p2Lng,p3Lat,p3Long).<br/>For example, `insideBoundingBox=47.3165,4.9665,47.3424,5.0201`).<br/>At indexing, you should specify geoloc of an object with the _geoloc attribute (in the form `"_geoloc":{"lat":48.853409, "lng":2.348800}` or `"_geoloc":[{"lat":48.853409, "lng":2.348800},{"lat":48.547456, "lng":2.972075}]` if you have several geo-locations in your record).
335
349
 
336
350
  #### Parameters to Control Results Content
337
351
 
@@ -342,6 +356,8 @@ You can use the following optional arguments:
342
356
  * **none**: If none of the query terms were found.
343
357
  * **attributesToSnippet**: A string that contains the list of attributes to snippet alongside the number of words to return (syntax is `attributeName:nbWords`). Attributes are separated by commas (Example: `attributesToSnippet=name:10,content:10`). <br/>You can also use a string array encoding (Example: `attributesToSnippet: ["name:10","content:10"]`). By default, no snippet is computed.
344
358
  * **getRankingInfo**: If set to 1, the result hits will contain ranking information in the **_rankingInfo** attribute.
359
+ * **highlightPreTag**: (string) Specify the string that is inserted before the highlighted parts in the query result (defaults to "&lt;em&gt;").
360
+ * **highlightPostTag**: (string) Specify the string that is inserted after the highlighted parts in the query result (defaults to "&lt;/em&gt;").
345
361
 
346
362
 
347
363
  #### Numeric Search Parameters
@@ -358,12 +374,29 @@ You can also use a string array encoding (for example `numericFilters: ["price>1
358
374
 
359
375
  #### Faceting Parameters
360
376
  * **facetFilters**: Filter the query with a list of facets. Facets are separated by commas and is encoded as `attributeName:value`. To OR facets, you must add parentheses. For example: `facetFilters=(category:Book,category:Movie),author:John%20Doe`. You can also use a string array encoding. For example, `[["category:Book","category:Movie"],"author:John%20Doe"]`.
361
- * **facets**: List of object attributes that you want to use for faceting. <br/>Attributes are separated with a comma. For example, `"category,author"`. You can also use JSON string array encoding. For example, `["category","author"]`. Only the attributes that have been added in **attributesForFaceting** index setting can be used in this parameter. You can also use `*` to perform faceting on all attributes specified in **attributesForFaceting**.
377
+ * **facets**: List of object attributes that you want to use for faceting. <br/>Attributes are separated with a comma. For example, `"category,author"`. You can also use JSON string array encoding. For example, `["category","author"]`. Only the attributes that have been added in **attributesForFaceting** index setting can be used in this parameter. You can also use `*` to perform faceting on all attributes specified in **attributesForFaceting**. If the number of results is important, the count can be approximate, the attribute `exhaustiveFacetsCount` in the response is true when the count is exact.
362
378
  * **maxValuesPerFacet**: Limit the number of facet values returned for each facet. For example, `maxValuesPerFacet=10` will retrieve a maximum of 10 values per facet.
363
379
 
380
+ #### UNIFIED FILTER PARAMETER (SQL LIKE)
381
+ * **filters**: Filter the query with numeric, facet or/and tag filters. The syntax is a SQL like syntax, you can use the OR and AND keywords. The syntax for the underlying numeric, facet and tag filters is the same than in the other filters:
382
+ `available=1 AND (category:Book OR NOT category:Ebook) AND public`
383
+ `date: 1441745506 TO 1441755506 AND inStock > 0 AND author:"John Doe"`
384
+ The list of keywords is:
385
+ **OR**: create a disjunctive filter between two filters.
386
+ **AND**: create a conjunctive filter between two filters.
387
+ **TO**: used to specify a range for a numeric filter.
388
+ **NOT**: used to negate a filter. The syntax with the ‘-‘ isn’t allowed.
389
+
390
+ *Note*: To specify a value with spaces or with a value equal to a keyword, it's possible to add quotes.
391
+
392
+ **Warning:**
393
+ * Like for the other filter for performance reason, it's not possible to have FILTER1 OR (FILTER2 AND FILTER3).
394
+ * It's not possible to mix different category of filter inside a OR like num=3 OR tag1 OR facet:value
395
+ * It's not possible to negate an group, it's only possible to negate a filters: NOT(FILTER1 OR (FILTER2) is not allowed.
396
+
397
+
364
398
  #### Distinct Parameter
365
399
  * **distinct**: If set to 1, enables the distinct feature, disabled by default, if the `attributeForDistinct` index setting is set. This feature is similar to the SQL "distinct" keyword. When enabled in a query with the `distinct=1` parameter, all hits containing a duplicate value for the attributeForDistinct attribute are removed from results. For example, if the chosen attribute is `show_name` and several hits have the same value for `show_name`, then only the best one is kept and the others are removed.
366
- **Note**: This feature is disabled if the query string is empty and there aren't any `tagFilters`, `facetFilters`, nor `numericFilters` parameters.
367
400
 
368
401
  ```ruby
369
402
  index = Algolia::Index.new("contacts")
@@ -407,6 +440,9 @@ The server response will look like:
407
440
  ```
408
441
 
409
442
 
443
+
444
+
445
+
410
446
  Multiple queries
411
447
  --------------
412
448
 
@@ -485,7 +521,7 @@ You can retrieve all settings using the `get_settings` function. The result will
485
521
  You can decide to have the same priority for two attributes by passing them in the same string using a comma as a separator. For example `title` and `alternative_title` have the same priority in this example, which is different than text priority: `attributesToIndex:["title,alternative_title", "text"]`.
486
522
  * **numericAttributesToIndex**: (array of strings) All numerical attributes are automatically indexed as numerical filters. If you don't need filtering on some of your numerical attributes, you can specify this list to speed up the indexing.<br/> If you only need to filter on a numeric value with the operator '=', you can speed up the indexing by specifying the attribute with `equalOnly(AttributeName)`. The other operators will be disabled.
487
523
  * **attributesForFaceting**: (array of strings) The list of fields you want to use for faceting. All strings in the attribute selected for faceting are extracted and added as a facet. If set to null, no attribute is used for faceting.
488
- * **attributeForDistinct**: The attribute name used for the `Distinct` feature. This feature is similar to the SQL "distinct" keyword. When enabled in queries with the `distinct=1` parameter, all hits containing a duplicate value for this attribute are removed from results. For example, if the chosen attribute is `show_name` and several hits have the same value for `show_name`, then only the best one is kept and others are removed. **Note**: This feature is disabled if the query string is empty and there aren't any `tagFilters`, `facetFilters`, nor `numericFilters` parameters.
524
+ * **attributeForDistinct**: The attribute name used for the `Distinct` feature. This feature is similar to the SQL "distinct" keyword. When enabled in queries with the `distinct=1` parameter, all hits containing a duplicate value for this attribute are removed from results. For example, if the chosen attribute is `show_name` and several hits have the same value for `show_name`, then only the best one is kept and others are removed.
489
525
  * **ranking**: (array of strings) Controls the way results are sorted.<br/>We have nine available criteria:
490
526
  * **typo**: Sort according to number of typos.
491
527
  * **geo**: Sort according to decreasing distance when performing a geo location based search.
@@ -513,7 +549,8 @@ You can decide to have the same priority for two attributes by passing them in t
513
549
  * **placeholders**: (hash of array of words). This is an advanced use case to define a token substitutable by a list of words without having the original token searchable. It is defined by a hash associating placeholders to lists of substitutable words. For example, `"placeholders": { "<streetnumber>": ["1", "2", "3", ..., "9999"]}` would allow it to be able to match all street numbers. We use the `< >` tag syntax to define placeholders in an attribute. For example:
514
550
  * Push a record with the placeholder: `{ "name" : "Apple Store", "address" : "&lt;streetnumber&gt; Opera street, Paris" }`.
515
551
  * Configure the placeholder in your index settings: `"placeholders": { "<streetnumber>" : ["1", "2", "3", "4", "5", ... ], ... }`.
516
- * **disableTypoToleranceOn**: (string array) Specify a list of words on which automatic typo tolerance will be disabled.
552
+ * **disableTypoToleranceOnWords**: (string array) Specify a list of words on which automatic typo tolerance will be disabled.
553
+ * **disableTypoToleranceOnAttributes**: (string array) List of attributes on which you want to disable typo tolerance (must be a subset of the `attributesToIndex` index setting). By default the list is empty.
517
554
  * **altCorrections**: (object array) Specify alternative corrections that you want to consider. Each alternative correction is described by an object containing three attributes:
518
555
  * **word**: The word to correct.
519
556
  * **correction**: The corrected word.
@@ -531,6 +568,26 @@ You can decide to have the same priority for two attributes by passing them in t
531
568
  * **highlightPreTag**: (string) Specify the string that is inserted before the highlighted parts in the query result (defaults to "&lt;em&gt;").
532
569
  * **highlightPostTag**: (string) Specify the string that is inserted after the highlighted parts in the query result (defaults to "&lt;/em&gt;").
533
570
  * **optionalWords**: (array of strings) Specify a list of words that should be considered optional when found in the query.
571
+ * **allowTyposOnNumericTokens**: (boolean) If set to false, disable typo-tolerance on numeric tokens (=numbers) in the query word. For example the query `"304"` will match with `"30450"`, but not with `"40450"` that would have been the case with typo-tolerance enabled. Can be very useful on serial numbers and zip codes searches. Default to false.
572
+ * **ignorePlurals**: (boolean) If set to true, simple plural forms won’t be considered as typos (for example car/cars will be considered as equal). Default to false.
573
+ * **advancedSyntax**: Enable the advanced query syntax. Defaults to 0 (false).
574
+
575
+ * **Phrase query:** a phrase query defines a particular sequence of terms. A phrase query is build by Algolia's query parser for words surrounded by `"`. For example, `"search engine"` will retrieve records having `search` next to `engine` only. Typo-tolerance is disabled on phrase queries.
576
+
577
+ * **Prohibit operator:** The prohibit operator excludes records that contain the term after the `-` symbol. For example `search -engine` will retrieve records containing `search` but not `engine`.
578
+ * **replaceSynonymsInHighlight**: (boolean) If set to false, words matched via synonyms expansion will not be replaced by the matched synonym in the highlighted result. Default to true.
579
+ * **maxValuesPerFacet**: (integer) Limit the number of facet values returned for each facet. For example: `maxValuesPerFacet=10` will retrieve max 10 values per facet.
580
+ * **distinct**: (integer) Enable the distinct feature (disabled by default) if the `attributeForDistinct` index setting is set. This feature is similar to the SQL "distinct" keyword: when enabled in a query with the `distinct=1` parameter, all hits containing a duplicate value for the`attributeForDistinct` attribute are removed from results. For example, if the chosen attribute is `show_name` and several hits have the same value for `show_name`, then only the best one is kept and others are removed.
581
+ * **typoTolerance**: (string) This setting has four different options:
582
+
583
+ * **true:** activate the typo-tolerance (default value).
584
+
585
+ * **false:** disable the typo-tolerance
586
+
587
+ * **min:** keep only results with the lowest number of typo. For example if one result match without typos, then all results with typos will be hidden.
588
+
589
+ * **strict:** if there is a match without typo, then all results with 2 typos or more will be removed. This option is useful if you want to avoid as much as possible false positive.
590
+ * **removeStopWords**: (boolean) Remove stop words from query before executing it. Defaults to false. Contains stop words for 41 languages (Arabic, Armenian, Basque, Bengali, Brazilian, Bulgarian, Catalan, Chinese, Czech, Danish, Dutch, English, Finnish, French, Galician, German, Greek, Hindi, Hungarian, Indonesian, Irish, Italian, Japanese, Korean, Kurdish, Latvian, Lithuanian, Marathi, Norwegian, Persian, Polish, Portugese, Romanian, Russian, Slovak, Spanish, Swedish, Thai, Turkish, Ukranian, Urdu)
534
591
 
535
592
  You can easily retrieve settings or update them:
536
593
 
@@ -594,7 +651,7 @@ Batch writes
594
651
  -------------
595
652
 
596
653
  You may want to perform multiple operations with one API call to reduce latency.
597
- We expose three methods to perform batch operations:
654
+ We expose four methods to perform batch operations:
598
655
  * `add_objects`: Add an array of objects using automatic `objectID` assignment.
599
656
  * `save_objects`: Add or update an array of objects that contains an `objectID` attribute.
600
657
  * `delete_objects`: Delete an array of objectIDs.
@@ -688,17 +745,17 @@ puts res['key']
688
745
 
689
746
  You can also create an API Key with advanced settings:
690
747
 
691
- * Add a validity period. The key will be valid for a specific period of time (in seconds).
692
- * Specify the maximum number of API calls allowed from an IP address per hour. Each time an API call is performed with this key, a check is performed. If the IP at the source of the call did more than this number of calls in the last hour, a 403 code is returned. Defaults to 0 (no rate limit). This parameter can be used to protect you from attempts at retrieving your entire index contents by massively querying the index.
748
+ * **validity**: Add a validity period. The key will be valid for a specific period of time (in seconds).
749
+ * **maxQueriesPerIPPerHour**: Specify the maximum number of API calls allowed from an IP address per hour. Each time an API call is performed with this key, a check is performed. If the IP at the source of the call did more than this number of calls in the last hour, a 403 code is returned. Defaults to 0 (no rate limit). This parameter can be used to protect you from attempts at retrieving your entire index contents by massively querying the index.
693
750
 
694
751
 
695
752
  Note: If you are sending the query through your servers, you must use the `Algolia.with_rate_limits("EndUserIP", "APIKeyWithRateLimit") do ... end` block to enable rate-limit.
696
753
 
697
- * Specify the maximum number of hits this API key can retrieve in one call. Defaults to 0 (unlimited). This parameter can be used to protect you from attempts at retrieving your entire index contents by massively querying the index.
698
- * Specify the list of targeted indices. You can target all indices starting with a prefix or ending with a suffix using the '*' character. For example, "dev_*" matches all indices starting with "dev_" and "*_dev" matches all indices ending with "_dev". Defaults to all indices if empty or blank.
699
- * Specify the list of referers. You can target all referers starting with a prefix or ending with a suffix using the '*' character. For example, "algolia.com/*" matches all referers starting with "algolia.com/" and "*.algolia.com" matches all referers ending with ".algolia.com". Defaults to all referers if empty or blank.
700
- * Specify the list of query parameters. You can force the query parameters for a query using the url string format (param1=X&param2=Y...).
701
- * Specify a description to describe where the key is used.
754
+ * **maxHitsPerQuery**: Specify the maximum number of hits this API key can retrieve in one call. Defaults to 0 (unlimited). This parameter can be used to protect you from attempts at retrieving your entire index contents by massively querying the index.
755
+ * **indexes**: Specify the list of targeted indices. You can target all indices starting with a prefix or ending with a suffix using the '\*' character. For example, "dev\_\*" matches all indices starting with "dev\_" and "\*\_dev" matches all indices ending with "\_dev". Defaults to all indices if empty or blank.
756
+ * **referers**: Specify the list of referers. You can target all referers starting with a prefix or ending with a suffix using the '\*' character. For example, "algolia.com/\*" matches all referers starting with "algolia.com/" and "\*.algolia.com" matches all referers ending with ".algolia.com". Defaults to all referers if empty or blank.
757
+ * **queryParameters**: Specify the list of query parameters. You can force the query parameters for a query using the url string format (param1=X&param2=Y...).
758
+ * **description**: Specify a description to describe where the key is used.
702
759
 
703
760
 
704
761
  ```ruby
@@ -761,14 +818,13 @@ You may have a single index containing per user data. In that case, all records
761
818
  ```ruby
762
819
  # generate a public API key for user 42. Here, records are tagged with:
763
820
  # - 'user_XXXX' if they are visible by user XXXX
764
- public_key = Algolia.generate_secured_api_key 'YourSearchOnlyApiKey', 'tagFilters=user_42'
821
+ public_key = Algolia.generate_secured_api_key 'YourSearchOnlyApiKey', {'tagFilters'=> 'user_42'}
765
822
  ```
766
823
 
767
824
  This public API key can then be used in your JavaScript code as follow:
768
825
 
769
826
  ```js
770
827
  var client = algoliasearch('YourApplicationID', '<%= public_api_key %>');
771
- client.setExtraHeader('X-Algolia-QueryParameters', 'tagFilters=user_42'); // must be same than those used at generation-time
772
828
 
773
829
  var index = client.initIndex('indexName')
774
830
 
@@ -782,12 +838,12 @@ index.search('something', function(err, content) {
782
838
  });
783
839
  ```
784
840
 
785
- You can mix rate limits and secured API keys by setting an extra `user_token` attribute both at API key generation time and query time. When set, a unique user will be identified by her `IP + user_token` instead of only by her `IP`. This allows you to restrict a single user to performing a maximum of `N` API calls per hour, even if she shares her `IP` with another user.
841
+ You can mix rate limits and secured API keys by setting a `userToken` query parameter at API key generation time. When set, a unique user will be identified by her `IP + user_token` instead of only by her `IP`. This allows you to restrict a single user to performing a maximum of `N` API calls per hour, even if she shares her `IP` with another user.
786
842
 
787
843
  ```ruby
788
844
  # generate a public API key for user 42. Here, records are tagged with:
789
845
  # - 'user_XXXX' if they are visible by user XXXX
790
- public_key = Algolia.generate_secured_api_key 'YourRateLimitedApiKey', 'tagFilters=user_42', 'user_42'
846
+ public_key = Algolia.generate_secured_api_key 'YourRateLimitedApiKey', {'tagFilters'=> 'user_42', 'userToken'=> 'user_42'}
791
847
  ```
792
848
 
793
849
  This public API key can then be used in your JavaScript code as follow:
@@ -795,32 +851,6 @@ This public API key can then be used in your JavaScript code as follow:
795
851
  ```js
796
852
  var client = algoliasearch('YourApplicationID', '<%= public_api_key %>');
797
853
 
798
- // must be same than those used at generation-time
799
- client.setExtraHeader('X-Algolia-QueryParameters', 'tagFilters=user_42');
800
-
801
- // must be same than the one used at generation-time
802
- client.setUserToken('user_42');
803
-
804
- var index = client.initIndex('indexName')
805
-
806
- index.search('another query', function(err, content) {
807
- if (err) {
808
- console.error(err);
809
- return;
810
- }
811
-
812
- console.log(content);
813
- });
814
- ```
815
-
816
- You can also generate secured API keys to limit the usage of a key to a referer. The generation use the same function than the Per user restriction. This public API key can be used in your JavaScript code as follow:
817
-
818
- ```js
819
- var client = algoliasearch('YourApplicationID', '<%= public_api_key %>');
820
-
821
- // must be same than those used at generation-time
822
- client.setExtraHeader('X-Algolia-AllowedReferer', 'algolia.com/*');
823
-
824
854
  var index = client.initIndex('indexName')
825
855
 
826
856
  index.search('another query', function(err, content) {
@@ -834,7 +864,6 @@ index.search('another query', function(err, content) {
834
864
  ```
835
865
 
836
866
 
837
-
838
867
  Copy or rename an index
839
868
  -------------
840
869
 
@@ -857,19 +886,25 @@ The move command is particularly useful if you want to update a big index atomic
857
886
  puts Algolia.move_index("MyNewIndex", "MyIndex")
858
887
  ```
859
888
 
889
+
860
890
  Backup / Retrieve of all index content
861
891
  -------------
862
892
 
863
893
  You can retrieve all index content for backup purposes or for SEO using the browse method.
864
- This method retrieves 1,000 objects via an API call and supports pagination.
894
+ This method can retrieve up to 1,000 objects per call and supports full text search and filters but the distinct feature is not available
895
+ Unlike the search method, the sort by typo, proximity, geo distance and matched words is not applied, the hits are only sorted by numeric attributes specified in the ranking and the custom ranking.
896
+
897
+ You can browse the index:
865
898
 
866
899
  ```ruby
867
- # Get first page
868
- puts index.browse(0)
869
- # Get second page
870
- puts index.browse(1)
900
+ # Iterate with a filter over the index
901
+ index.browse({:query => "test", :numericFilters => 'i=42'}) do
902
+ # Do something
903
+ end
871
904
  ```
872
905
 
906
+
907
+
873
908
  Logs
874
909
  -------------
875
910
 
@@ -919,7 +954,7 @@ describe 'With a mocked client' do
919
954
  it "shouldn't perform any API calls here" do
920
955
  index = Algolia::Index.new("friends")
921
956
  index.add_object!({ :name => "John Doe", :email => "john@doe.org" })
922
- index.search('').should == {} # mocked
957
+ index.search('').should == {"hits"=>[{"objectID"=>42}], "page"=>1, "hitsPerPage"=>1} # mocked
923
958
  index.clear_index
924
959
  index.delete_index
925
960
  end
@@ -4,6 +4,7 @@ require 'algolia/version'
4
4
  require 'json'
5
5
  require 'zlib'
6
6
  require 'openssl'
7
+ require 'base64'
7
8
 
8
9
  module Algolia
9
10
 
@@ -98,7 +99,9 @@ module Algolia
98
99
  def multiple_queries(queries, index_name_key = :index_name, strategy = "none")
99
100
  requests = {
100
101
  :requests => queries.map do |query|
102
+ query = query.dup
101
103
  indexName = query.delete(index_name_key) || query.delete(index_name_key.to_s)
104
+ raise ArgumentError.new("Missing '#{index_name_key}' option") if indexName.nil?
102
105
  encoded_params = Hash[query.map { |k,v| [k.to_s, v.is_a?(Array) ? v.to_json : v] }]
103
106
  { :indexName => indexName, :params => Protocol.to_query(encoded_params) }
104
107
  end
@@ -469,12 +472,21 @@ module Algolia
469
472
  # @param tag_filters the list of tags applied to the query (used as security)
470
473
  # @param user_token an optional token identifying the current user
471
474
  #
472
- def Algolia.generate_secured_api_key(private_api_key, tag_filters, user_token = nil)
473
- if tag_filters.is_a?(Array)
474
- tag_filters = tag_filters.map { |t| t.is_a?(Array) ? "(#{t.join(',')})" : t }.join(',')
475
+ def Algolia.generate_secured_api_key(private_api_key, tag_filters_or_params, user_token = nil)
476
+ if tag_filters_or_params.is_a?(Hash) && user_token.nil?
477
+ encoded_params = Hash[tag_filters_or_params.map { |k,v| [k.to_s, v.is_a?(Array) ? v.to_json : v] }]
478
+ query_str = Protocol.to_query(encoded_params)
479
+ hmac = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), private_api_key, query_str)
480
+ Base64.encode64("#{hmac}#{query_str}").gsub("\n", '')
481
+ else
482
+ tag_filters = if tag_filters_or_params.is_a?(Array)
483
+ tag_filters = tag_filters_or_params.map { |t| t.is_a?(Array) ? "(#{t.join(',')})" : t }.join(',')
484
+ else
485
+ tag_filters_or_params
486
+ end
487
+ raise ArgumentError.new('Attribute "tag_filters" must be a list of tags') if !tag_filters.is_a?(String)
488
+ OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), private_api_key, "#{tag_filters}#{user_token.to_s}")
475
489
  end
476
- raise ArgumentError.new('Attribute "tag_filters" must be a list of tags') if !tag_filters.is_a?(String)
477
- OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), private_api_key, "#{tag_filters}#{user_token.to_s}")
478
490
  end
479
491
 
480
492
  #
@@ -1,3 +1,3 @@
1
1
  module Algolia
2
- VERSION = "1.6.1"
2
+ VERSION = "1.7.0"
3
3
  end
@@ -1,5 +1,6 @@
1
1
  # encoding: UTF-8
2
2
  require File.expand_path(File.join(File.dirname(__FILE__), 'spec_helper'))
3
+ require 'base64'
3
4
 
4
5
  # avoid concurrent access to the same index
5
6
  def safe_index_name(name)
@@ -277,6 +278,10 @@ describe 'Client' do
277
278
  res["results"][0]["hits"].length.should eq(1)
278
279
  end
279
280
 
281
+ it "should throw if the index_name is missing in multiple_queries" do
282
+ expect { Algolia.multiple_queries([{"query" => ""}]) }.to raise_error(ArgumentError)
283
+ end
284
+
280
285
  it "shoud accept custom batch" do
281
286
  @index.clear_index! rescue "Not fatal"
282
287
  request = { "requests" => [
@@ -647,7 +652,7 @@ describe 'Client' do
647
652
  logs['logs'][0]['sha1'].should be_a(String)
648
653
  end
649
654
 
650
- it 'should generate secured api keys' do
655
+ it 'should generate secured api keys (old syntax)' do
651
656
  key = Algolia.generate_secured_api_key('my_api_key', '(public,user1)')
652
657
  key.should eq(OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), 'my_api_key', '(public,user1)'))
653
658
  key = Algolia.generate_secured_api_key('my_api_key', '(public,user1)', 42)
@@ -658,6 +663,13 @@ describe 'Client' do
658
663
  key.should eq(OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), 'my_api_key', 'public,(premium,vip)'))
659
664
  end
660
665
 
666
+ it 'should generate secured api keys (new syntax)' do
667
+ key = Algolia.generate_secured_api_key('my_api_key', :tagFilters => '(public,user1)')
668
+ key.should eq(Base64.encode64("#{OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), 'my_api_key', 'tagFilters=%28public%2Cuser1%29')}tagFilters=%28public%2Cuser1%29").gsub("\n", ''))
669
+ key = Algolia.generate_secured_api_key('182634d8894831d5dbce3b3185c50881', :tagFilters => '(public,user1)', :userToken => 42)
670
+ key.should eq('OGYwN2NlNTdlOGM2ZmM4MjA5NGM0ZmYwNTk3MDBkNzMzZjQ0MDI3MWZjNTNjM2Y3YTAzMWM4NTBkMzRiNTM5YnRhZ0ZpbHRlcnM9JTI4cHVibGljJTJDdXNlcjElMjkmdXNlclRva2VuPTQy')
671
+ end
672
+
661
673
  it 'Check attributes multipleQueries' do
662
674
  res = Algolia.multiple_queries([{:index_name => safe_index_name("àlgol?a"), "query" => ""}])
663
675
  res.should have_key('results')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: algoliasearch
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.1
4
+ version: 1.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Algolia
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-07-31 00:00:00.000000000 Z
11
+ date: 2016-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httpclient