algoliasearch 1.11.0 → 1.12.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: 2a37e65bca2bf7c296add2c0f0187ab5bd33eedb
4
- data.tar.gz: 7889a0cce2a6470260c3616ca71fda9022084792
3
+ metadata.gz: 47343e37f75fab97f3f03b5077d1422376a0995f
4
+ data.tar.gz: d0c473b3587f99c0b64410fea213dd73f4e83ae9
5
5
  SHA512:
6
- metadata.gz: db44fe908876413039e4efb0a447f9fbf7b95a3cbd11e0401d1bb53500e13d4d6b133772bb7b589c96b4de08f178a50443f101285df47a8e917c6b21c8a8d79a
7
- data.tar.gz: 04f539db59d6de73e6d088b19b80a2182d1f931c5649e0c6af5fc4e968bd4fc698e4a9797c88a1041e1b0dc843a0a9c599892441893645330a605a07c7bdf230
6
+ metadata.gz: 2c853a919b2dc0a269b28890fa431576dd55424776c77a784dab5bf4e0c536456f9ad1fb67e3a0378ba6f45c3c832f5b018e104866ec5ee731010550c5ffc347
7
+ data.tar.gz: 5e12669bdc370347f622652079fe882ed836ae6726fe123cc8d2ddfc8b80c6a1a395525dc5ae96fc33a55f4896fc37f0e0f746d1b550773979c5480cf44c4d28
data/.travis.yml CHANGED
@@ -11,6 +11,9 @@ rvm:
11
11
  - 2.3.1
12
12
  - jruby
13
13
  - rbx-2
14
+ matrix:
15
+ allow_failures:
16
+ - rvm: rbx-2
14
17
  cache: bundler
15
18
  env:
16
19
  global:
data/ChangeLog CHANGED
@@ -1,5 +1,8 @@
1
1
  CHANGELOG
2
2
 
3
+ 2016-10-31 1.12.0
4
+ * Add `search_facet`
5
+
3
6
  2016-08-21 1.11.0
4
7
  * Upgraded to httpclient 2.8.1 to avoid reseting the keep-alive while changing timeouts
5
8
 
data/Gemfile CHANGED
@@ -1,6 +1,6 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'httpclient', '~> 2.8.2'
3
+ gem 'httpclient', '~> 2.8.2.4'
4
4
  gem 'json', '>= 1.5.1'
5
5
  gem 'rubysl', '~> 2.0', :platform => :rbx
6
6
 
data/Gemfile.lock CHANGED
@@ -31,7 +31,7 @@ GEM
31
31
  net-http-persistent (>= 2.7)
32
32
  net-http-pipeline
33
33
  highline (1.6.21)
34
- httpclient (2.8.2.2)
34
+ httpclient (2.8.2.4)
35
35
  json (1.8.3)
36
36
  json (1.8.3-java)
37
37
  launchy (2.4.3)
@@ -311,7 +311,7 @@ PLATFORMS
311
311
  DEPENDENCIES
312
312
  coveralls
313
313
  highline (< 1.7.0)
314
- httpclient (~> 2.8.2)
314
+ httpclient (~> 2.8.2.4)
315
315
  json (>= 1.5.1)
316
316
  mime-types (< 2.0)
317
317
  rake
@@ -323,6 +323,3 @@ DEPENDENCIES
323
323
  simplecov
324
324
  travis
325
325
  webmock
326
-
327
- BUNDLED WITH
328
- 1.11.2
data/README.md CHANGED
@@ -48,7 +48,7 @@ Indexing
48
48
 
49
49
  1. [Add objects](#add-objects---add_objects)
50
50
  1. [Update objects](#update-objects---save_objects)
51
- 1. [Partial update](#partial-update---partial_update_objects)
51
+ 1. [Partial update objects](#partial-update-objects---partial_update_objects)
52
52
  1. [Delete objects](#delete-objects---delete_objects)
53
53
 
54
54
  Settings
@@ -196,7 +196,7 @@ index.set_settings({"customRanking" => ["desc(followers)"]})
196
196
  You can also configure the list of attributes you want to index by order of importance (first = most important):
197
197
 
198
198
  ```ruby
199
- index.set_settings({"attributesToIndex" => ["lastname", "firstname", "company",
199
+ index.set_settings({"searchableAttributes" => ["lastname", "firstname", "company",
200
200
  "email", "city", "address"]})
201
201
  ```
202
202
 
@@ -358,17 +358,17 @@ The server response will look like:
358
358
 
359
359
  - `nbHits` (integer): Number of hits that the search query matched.
360
360
 
361
- - `page` (integer): Index of the current page (zero-based). See the [`page`](#page) search parameter.
361
+ - `page` (integer): Index of the current page (zero-based). See the [`page`](#page) search parameter. *Note: Not returned if you use `offset`/`length` for pagination.*
362
362
 
363
- - `hitsPerPage` (integer): Maximum number of hits returned per page. See the [`hitsPerPage`](#hitsperpage) search parameter.
363
+ - `hitsPerPage` (integer): Maximum number of hits returned per page. See the [`hitsPerPage`](#hitsperpage) search parameter. *Note: Not returned if you use `offset`/`length` for pagination.*
364
364
 
365
- - `nbPages` (integer): Number of pages corresponding to the number of hits. Basically, `ceil(nbHits / hitsPerPage)`.
365
+ - `nbPages` (integer): Number of pages corresponding to the number of hits. Basically, `ceil(nbHits / hitsPerPage)`. *Note: Not returned if you use `offset`/`length` for pagination.*
366
366
 
367
367
  - `processingTimeMS` (integer): Time that the server took to process the request, in milliseconds. *Note: This does not include network time.*
368
368
 
369
369
  - `query` (string): An echo of the query text. See the [`query`](#query) search parameter.
370
370
 
371
- - `queryAfterRemoval` (string, optional): *Note: Only returned when [`removeWordsIfNoResults`](#removewordsifnoresults) is set.* A markup text indicating which parts of the original query have been removed in order to retrieve a non-empty result set. The removed parts are surrounded by `<em>` tags.
371
+ - `queryAfterRemoval` (string, optional): *Note: Only returned when [`removeWordsIfNoResults`](#removewordsifnoresults) is set to `lastWords` or `firstWords`.* A markup text indicating which parts of the original query have been removed in order to retrieve a non-empty result set. The removed parts are surrounded by `<em>` tags.
372
372
 
373
373
  - `params` (string, URL-encoded): An echo of all search parameters.
374
374
 
@@ -382,7 +382,7 @@ When [`getRankingInfo`](#getrankinginfo) is set to `true`, the following additio
382
382
 
383
383
  - `serverUsed` (string): Actual host name of the server that processed the request. (Our DNS supports automatic failover and load balancing, so this may differ from the host name used in the request.)
384
384
 
385
- - `parsedQuery` (string): The query string that will be searched, after normalization.
385
+ - `parsedQuery` (string): The query string that will be searched, after normalization. Normalization includes removing stop words (if [removeStopWords](#removestopwords) is enabled), and transforming portions of the query string into phrase queries (see [advancedSyntax](#advancedsyntax)).
386
386
 
387
387
  - `timeoutCounts` (boolean): Whether a timeout was hit when computing the facet counts. When `true`, the counts will be interpolated (i.e. approximate). See also `exhaustiveFacetsCount`.
388
388
 
@@ -426,6 +426,7 @@ Parameters that can also be used in a setSettings also have the `indexing` [scop
426
426
  **Attributes**
427
427
 
428
428
  - [attributesToRetrieve](#attributestoretrieve) `settings`, `search`
429
+ - [restrictSearchableAttributes](#restrictsearchableattributes) `search`
429
430
 
430
431
  **Filtering / Faceting**
431
432
 
@@ -440,11 +441,14 @@ Parameters that can also be used in a setSettings also have the `indexing` [scop
440
441
  - [highlightPreTag](#highlightpretag) `settings`, `search`
441
442
  - [highlightPostTag](#highlightposttag) `settings`, `search`
442
443
  - [snippetEllipsisText](#snippetellipsistext) `settings`, `search`
444
+ - [restrictHighlightAndSnippetArrays](#restricthighlightandsnippetarrays) `settings`, `search`
443
445
 
444
446
  **Pagination**
445
447
 
446
448
  - [page](#page) `search`
447
449
  - [hitsPerPage](#hitsperpage) `settings`, `search`
450
+ - [offset](#offset) `search`
451
+ - [length](#length) `search`
448
452
 
449
453
  **Typos**
450
454
 
@@ -472,6 +476,7 @@ Parameters that can also be used in a setSettings also have the `indexing` [scop
472
476
  - [advancedSyntax](#advancedsyntax) `settings`, `search`
473
477
  - [optionalWords](#optionalwords) `settings`, `search`
474
478
  - [removeStopWords](#removestopwords) `settings`, `search`
479
+ - [disableExactOnAttributes](#disableexactonattributes) `settings`, `search`
475
480
  - [exactOnSingleWordQuery](#exactonsinglewordquery) `settings`, `search`
476
481
  - [alternativesAsExact](#alternativesasexact) `settings`, `search`
477
482
 
@@ -483,9 +488,47 @@ Parameters that can also be used in a setSettings also have the `indexing` [scop
483
488
  - [tagFilters (deprecated)](#tagfilters-deprecated) `search`
484
489
  - [facetFilters (deprecated)](#facetfilters-deprecated) `search`
485
490
  - [analytics](#analytics) `search`
491
+ - [analyticsTags](#analyticstags) `search`
492
+ - [synonyms](#synonyms) `search`
493
+ - [replaceSynonymsInHighlight](#replacesynonymsinhighlight) `search`, `settings`
494
+ - [minProximity](#minproximity) `search`, `settings`
486
495
 
487
496
  <!--/PARAMETERS_LINK-->
488
497
 
498
+ ### Multiple queries - `multiple_queries`
499
+
500
+ You can send multiple queries with a single API call using a batch of queries:
501
+
502
+ ```ruby
503
+ # perform 3 queries in a single API call:
504
+ # - 1st query targets index `categories`
505
+ # - 2nd and 3rd queries target index `products`
506
+ res = Algolia.multiple_queries([{:index_name => "categories", "query" => my_query_string, "hitsPerPage" => 3}
507
+ , {:index_name => "products", "query" => my_query_string, "hitsPerPage" => 3, "filters" => "_tags:promotion"}
508
+ , {:index_name => "products", "query" => my_query_string, "hitsPerPage" => 10}])
509
+
510
+ puts res["results"]
511
+ ```
512
+
513
+ You can specify a `strategy` parameter to optimize your multiple queries:
514
+
515
+ - `none`: Execute the sequence of queries until the end.
516
+ - `stopIfEnoughMatches`: Execute the sequence of queries until the number of hits is reached by the sum of hits.
517
+
518
+ #### Response
519
+
520
+ The resulting JSON contains the following fields:
521
+
522
+ - `results` (array): The results for each request, in the order they were submitted. The contents are the same as in [Search in an index](#search-in-an-index---search).
523
+
524
+ Each result also includes the following additional fields:
525
+
526
+ - `index` (string): The name of the targeted index.
527
+
528
+ - `processed` (boolean, optional): *Note: Only returned when `strategy` is `stopIfEnoughmatches`.* Whether the query was processed.
529
+
530
+
531
+
489
532
  ### Find by IDs - `get_objects`
490
533
 
491
534
  You can easily retrieve an object using its `objectID` and optionally specify a comma separated list of attributes you want:
@@ -516,21 +559,33 @@ res = index.get_objects(["myID", "myID2"])
516
559
 
517
560
  Each entry in an index has a unique identifier called `objectID`. There are two ways to add an entry to the index:
518
561
 
519
- 1. Using automatic `objectID` assignment. You will be able to access it in the answer.
520
- 2. Supplying your own `objectID`.
562
+ 1. Supplying your own `objectID`.
563
+ 2. Using automatic `objectID` assignment. You will be able to access it in the answer.
521
564
 
522
565
  You don't need to explicitly create an index, it will be automatically created the first time you add an object.
523
566
  Objects are schema less so you don't need any configuration to start indexing. If you wish to configure things, the settings section provides details about advanced settings.
524
567
 
525
- Example with automatic `objectID` assignment:
568
+ Example with automatic `objectID` assignments:
526
569
 
527
570
  ```ruby
528
- res = index.add_object({"firstname" => "Jimmie",
529
- "lastname" => "Barninger"})
530
- puts "ObjectID=" + res["objectID"]
571
+ res = index.add_objects([{"firstname" => "Jimmie",
572
+ "lastname" => "Barninger"},
573
+ {"firstname" => "Warren",
574
+ "lastname" => "Speach"}])
531
575
  ```
532
576
 
533
- Example with manual `objectID` assignment:
577
+ Example with manual `objectID` assignments:
578
+
579
+ ```ruby
580
+ res = index.add_objects([{"objectID" => "1",
581
+ "firstname" => "Jimmie",
582
+ "lastname" => "Barninger"},
583
+ {"objectID" => "2",
584
+ "firstname" => "Warren",
585
+ "lastname" => "Speach"}])
586
+ ```
587
+
588
+ To add a single object, use the `[Add object](#add-object---add_object)` method:
534
589
 
535
590
  ```ruby
536
591
  res = index.add_object({"firstname" => "Jimmie",
@@ -538,7 +593,6 @@ res = index.add_object({"firstname" => "Jimmie",
538
593
  puts "ObjectID=" + res["objectID"]
539
594
  ```
540
595
 
541
-
542
596
  ### Update objects - `save_objects`
543
597
 
544
598
  You have three options when updating an existing object:
@@ -547,7 +601,18 @@ You have three options when updating an existing object:
547
601
  2. Replace only some attributes.
548
602
  3. Apply an operation to some attributes.
549
603
 
550
- Example on how to replace all attributes of an existing object:
604
+ Example on how to replace all attributes existing objects:
605
+
606
+ ```ruby
607
+ res = index.save_objects([{"firstname" => "Jimmie",
608
+ "lastname" => "Barninger",
609
+ "objectID" => "myID1"},
610
+ {"firstname" => "Warren",
611
+ "lastname" => "Speach",
612
+ "objectID" => "myID2"}])
613
+ ```
614
+
615
+ To update a single object, you can use the `[Update object](#update-object---save_object) method:
551
616
 
552
617
  ```ruby
553
618
  index.save_object({"firstname" => "Jimmie",
@@ -556,7 +621,8 @@ index.save_object({"firstname" => "Jimmie",
556
621
  "objectID" => "myID"})
557
622
  ```
558
623
 
559
- ### Partial update - `partial_update_objects`
624
+
625
+ ### Partial update objects - `partial_update_objects`
560
626
 
561
627
  You have many ways to update an object's attributes:
562
628
 
@@ -615,10 +681,25 @@ index.partial_update_object({"price" => {"value" => 42, "_operation" => "Decreme
615
681
  Note: Here we are decrementing the value by `42`. To decrement just by one, put
616
682
  `value:1`.
617
683
 
684
+ To partial update multiple objects using one API call, you can use the `[Partial update objects](#partial-update-objects---partial_update_objects)` method:
685
+
686
+ ```ruby
687
+ res = index.partial_update_objects([{"firstname" => "Jimmie",
688
+ "objectID" => "SFO"},
689
+ {"firstname" => "Warren",
690
+ "objectID" => "myID2"}])
691
+ ```
692
+
618
693
 
619
694
  ### Delete objects - `delete_objects`
620
695
 
621
- You can delete an object using its `objectID`:
696
+ You can delete objects using their `objectID`:
697
+
698
+ ```ruby
699
+ res = index.delete_objects(["myID1", "myID2"])
700
+ ```
701
+
702
+ To delete a single object, you can use the `[Delete object](#delete-object---delete_object)` method:
622
703
 
623
704
  ```ruby
624
705
  index.delete_object("myID")
@@ -668,7 +749,7 @@ the biggest `taskID` with `wait_task`.
668
749
  You can retrieve settings:
669
750
 
670
751
  ```ruby
671
- res = index.get_settings
752
+ settings = index.get_settings
672
753
  puts settings.to_json
673
754
  ```
674
755
 
@@ -682,12 +763,12 @@ index.set_settings({"customRanking" => ["desc(followers)"]})
682
763
 
683
764
  Performance wise, it's better to do a `set_settings` before pushing the data
684
765
 
685
- #### Slave settings
766
+ #### Replica settings
686
767
 
687
- You can forward all settings updates to the slaves of an index by using the `forwardToSlaves` option:
768
+ You can forward all settings updates to the replicas of an index by using the `forwardToReplicas` option:
688
769
 
689
770
  ```ruby
690
- index.set_settings({"customRanking" => ["desc(followers)"]}, {"forwardToSlave" => true})
771
+ index.set_settings({"customRanking" => ["desc(followers)"]}, {"forwardToReplicas" => true})
691
772
  ```
692
773
 
693
774
 
@@ -696,14 +777,14 @@ index.set_settings({"customRanking" => ["desc(followers)"]}, {"forwardToSlave" =
696
777
 
697
778
  <!--PARAMETERS_LINK-->
698
779
 
699
- Here is the list of parameters you can use with the set settings method (`indexing` [scope](#scope))
780
+ Here is the list of parameters you can use with the set settings method (`settings` [scope](#scope)).
700
781
 
701
782
 
702
- Parameters that can be overridden at search time also have the `search` [scope](#scope)
783
+ Parameters that can be overridden at search time also have the `search` [scope](#scope).
703
784
 
704
785
  **Attributes**
705
786
 
706
- - [attributesToIndex](#attributestoindex) `settings`
787
+ - [searchableAttributes](#searchableattributes) `settings`
707
788
  - [attributesForFaceting](#attributesforfaceting) `settings`
708
789
  - [attributesToRetrieve](#attributestoretrieve) `settings`, `search`
709
790
  - [unretrievableAttributes](#unretrievableattributes) `settings`
@@ -712,7 +793,7 @@ Parameters that can be overridden at search time also have the `search` [scope](
712
793
 
713
794
  - [ranking](#ranking) `settings`
714
795
  - [customRanking](#customranking) `settings`
715
- - [slaves](#slaves) `settings`
796
+ - [replicas](#replicas) `settings`
716
797
 
717
798
  **Filtering / Faceting**
718
799
 
@@ -756,7 +837,7 @@ Parameters that can be overridden at search time also have the `search` [scope](
756
837
 
757
838
  - [attributeForDistinct](#attributefordistinct) `settings`
758
839
  - [distinct](#distinct) `settings`, `search`
759
- - [numericAttributesToIndex](#numericattributestoindex) `settings`
840
+ - [numericAttributesForFiltering](#numericattributesforfiltering) `settings`
760
841
  - [allowCompressionOfIntegerArray](#allowcompressionofintegerarray) `settings`
761
842
  - [altCorrections](#altcorrections) `settings`
762
843
  - [placeholders](#placeholders) `settings`
@@ -788,17 +869,17 @@ They are three scopes:
788
869
 
789
870
  **Attributes**
790
871
 
872
+ - [searchableAttributes](#searchableattributes) `settings`
791
873
  - [attributesForFaceting](#attributesforfaceting) `settings`
792
- - [attributesToIndex](#attributestoindex) `settings`
793
- - [attributesToRetrieve](#attributestoretrieve) `settings`, `search`
794
874
  - [unretrievableAttributes](#unretrievableattributes) `settings`
795
-
875
+ - [attributesToRetrieve](#attributestoretrieve) `settings`, `search`
876
+ - [restrictSearchableAttributes](#restrictsearchableattributes) `search`
796
877
 
797
878
  **Ranking**
798
879
 
799
880
  - [ranking](#ranking) `settings`
800
881
  - [customRanking](#customranking) `settings`
801
- - [slaves](#slaves) `settings`
882
+ - [replicas](#replicas) `settings`
802
883
 
803
884
  **Filtering / Faceting**
804
885
 
@@ -819,6 +900,8 @@ They are three scopes:
819
900
 
820
901
  - [page](#page) `search`
821
902
  - [hitsPerPage](#hitsperpage) `settings`, `search`
903
+ - [offset](#offset) `search`
904
+ - [length](#length) `search`
822
905
 
823
906
  **Typos**
824
907
 
@@ -857,14 +940,18 @@ They are three scopes:
857
940
  - [attributeForDistinct](#attributefordistinct) `settings`
858
941
  - [distinct](#distinct) `settings`, `search`
859
942
  - [getRankingInfo](#getrankinginfo) `search`
860
- - [numericAttributesToIndex](#numericattributestoindex) `settings`
943
+ - [numericAttributesForFiltering](#numericattributesforfiltering) `settings`
861
944
  - [allowCompressionOfIntegerArray](#allowcompressionofintegerarray) `settings`
862
945
  - [numericFilters (deprecated)](#numericfilters-deprecated) `search`
863
946
  - [tagFilters (deprecated)](#tagfilters-deprecated) `search`
864
947
  - [facetFilters (deprecated)](#facetfilters-deprecated) `search`
865
948
  - [analytics](#analytics) `search`
866
- - [altCorrections](#altcorrections) `settings`
949
+ - [analyticsTags](#analyticstags) `search`
950
+ - [synonyms](#synonyms) `search`
951
+ - [replaceSynonymsInHighlight](#replacesynonymsinhighlight) `search`, `settings`
867
952
  - [placeholders](#placeholders) `settings`
953
+ - [altCorrections](#altcorrections) `settings`
954
+ - [minProximity](#minproximity) `search`, `settings`
868
955
 
869
956
  ### Search
870
957
 
@@ -879,11 +966,12 @@ The instant search query string, used to set the string you want to search in yo
879
966
 
880
967
  ### Attributes
881
968
 
882
- #### attributesToIndex
969
+ #### searchableAttributes
883
970
 
884
971
  - scope: `settings`
885
972
  - type: `array of strings`
886
973
  - default: `*`
974
+ - formerly known as: `attributesToIndex`
887
975
 
888
976
 
889
977
  The list of attributes you want index (i.e. to make searchable).
@@ -895,7 +983,7 @@ This parameter has two important uses:
895
983
 
896
984
  1. **Limit the attributes to index.** For example, if you store the URL of a picture, you want to store it and be able to retrieve it, but you probably don't want to search in the URL.
897
985
 
898
- 2. **Control part of the ranking.** The contents of the `attributesToIndex` parameter impacts ranking in two complementary ways:
986
+ 2. **Control part of the ranking.** The contents of the `searchableAttributes` parameter impacts ranking in two complementary ways:
899
987
 
900
988
  First, the order in which attributes are listed defines their ranking priority: matches in attributes at the beginning of the list will be considered more important than matches in attributes further down the list. To assign the same priority to several attributes, pass them within the same string, separated by commas. For example, by specifying `["title,"alternative_title", "text"]`, `title` and `alternative_title` will have the same priority, but a higher priority than `text`.
901
989
 
@@ -950,13 +1038,13 @@ You can also use `*` to retrieve all values when an **attributesToRetrieve** set
950
1038
 
951
1039
  - scope: `search`
952
1040
  - type: `array of strings`
953
- - default: `attributesToIndex`
1041
+ - default: `searchableAttributes`
954
1042
 
955
1043
 
956
- List of attributes you want to use for textual search (must be a subset of the `attributesToIndex` index setting).
1044
+ List of attributes you want to use for textual search (must be a subset of the `searchableAttributes` index setting).
957
1045
  Attributes are separated with a comma such as `"name,address"`.
958
1046
  You can also use JSON string array encoding such as `encodeURIComponent("[\"name\",\"address\"]")`.
959
- By default, all attributes specified in the `attributesToIndex` settings are used to search.
1047
+ By default, all attributes specified in the `searchableAttributes` settings are used to search.
960
1048
 
961
1049
 
962
1050
  ### Ranking
@@ -976,7 +1064,7 @@ We have nine available criterion:
976
1064
  * `geo`: Sort according to decreasing distance when performing a geo location based search.
977
1065
  * `words`: Sort according to the number of query words matched by decreasing order. This parameter is useful when you use the `optionalWords` query parameter to have results with the most matched words first.
978
1066
  * `proximity`: Sort according to the proximity of the query words in hits.
979
- * `attribute`: Sort according to the order of attributes defined by attributesToIndex.
1067
+ * `attribute`: Sort according to the order of attributes defined by searchableAttributes.
980
1068
  * `exact`:
981
1069
  * If the user query contains one word: sort objects having an attribute that is exactly the query word before others. For example, if you search for the TV show "V", you want to find it with the "V" query and avoid getting all popular TV shows starting by the letter V before it.
982
1070
  * If the user query contains multiple words: sort according to the number of words that matched exactly (not as a prefix).
@@ -1004,11 +1092,12 @@ For example, `"customRanking" => ["desc(population)", "asc(name)"]`.
1004
1092
  To get a full description of how the Custom Ranking works,
1005
1093
  you can have a look at our [Ranking guide](https://www.algolia.com/doc/guides/relevance/ranking).
1006
1094
 
1007
- #### slaves
1095
+ #### replicas
1008
1096
 
1009
1097
  - scope: `settings`
1010
1098
  - type: `array of strings`
1011
1099
  - default: `[]`
1100
+ - formerly known as: `slaves`
1012
1101
 
1013
1102
 
1014
1103
  The list of indices on which you want to replicate all write operations.
@@ -1019,7 +1108,7 @@ If you want to use different ranking configurations depending of the use case,
1019
1108
  you need to create one index per ranking configuration.
1020
1109
 
1021
1110
  This option enables you to perform write operations only on this index and automatically
1022
- update slave indices with the same operations.
1111
+ update replica indices with the same operations.
1023
1112
 
1024
1113
  ### Filtering / Faceting
1025
1114
 
@@ -1105,6 +1194,10 @@ Limit the number of facet values returned for each facet.
1105
1194
 
1106
1195
  For example, `maxValuesPerFacet=10` will retrieve a maximum of 10 values per facet.
1107
1196
 
1197
+ **Warnings**
1198
+
1199
+ - The engine has a hard limit on the `maxValuesPerFacet` of `1000`. Any value above that will be interpreted by the engine as being `1000`.
1200
+
1108
1201
  ### Highlighting / Snippeting
1109
1202
 
1110
1203
  #### attributesToHighlight
@@ -1204,6 +1297,28 @@ Pagination parameter used to select the page to retrieve.
1204
1297
 
1205
1298
  Pagination parameter used to select the number of hits per page.
1206
1299
 
1300
+ #### offset
1301
+
1302
+ - scope: `search`
1303
+ - type: `integer`
1304
+ - default: `null`
1305
+
1306
+
1307
+ Offset of the first hit to return (zero-based).
1308
+
1309
+ **Warning:** In most cases, `page`/`hitsPerPage` is the recommended method for pagination; `offset`/`length` is reserved for advanced use.
1310
+
1311
+ #### length
1312
+
1313
+ - scope: `search`
1314
+ - type: `integer`
1315
+ - default: `null`
1316
+
1317
+
1318
+ Number of hits to return.
1319
+
1320
+ **Warning:** In most cases, `page`/`hitsPerPage` is the recommended method for pagination; `offset`/`length` is reserved for advanced use.
1321
+
1207
1322
  ### Typos
1208
1323
 
1209
1324
  #### minWordSizefor1Typo
@@ -1265,7 +1380,7 @@ If set to true, plural won't be considered as a typo. For example, car and cars,
1265
1380
 
1266
1381
 
1267
1382
  List of attributes on which you want to disable typo tolerance
1268
- (must be a subset of the `attributesToIndex` index setting).
1383
+ (must be a subset of the `searchableAttributes` index setting).
1269
1384
 
1270
1385
  Attributes are separated with a comma such as `"name,address"`.
1271
1386
  You can also use JSON string array encoding such as `encodeURIComponent("[\"name\",\"address\"]")`.
@@ -1523,7 +1638,7 @@ For most use cases, it is better to not use this feature as people search by key
1523
1638
 
1524
1639
 
1525
1640
  List of attributes on which you want to disable prefix matching
1526
- (must be a subset of the `attributesToIndex` index setting).
1641
+ (must be a subset of the `searchableAttributes` index setting).
1527
1642
 
1528
1643
  This setting is useful on attributes that contain string that should not be matched as a prefix
1529
1644
  (for example a product SKU).
@@ -1537,7 +1652,7 @@ This setting is useful on attributes that contain string that should not be matc
1537
1652
 
1538
1653
 
1539
1654
  List of attributes on which you want to disable the computation of `exact` criteria
1540
- (must be a subset of the `attributesToIndex` index setting).
1655
+ (must be a subset of the `searchableAttributes` index setting).
1541
1656
 
1542
1657
  #### exactOnSingleWordQuery
1543
1658
 
@@ -1617,11 +1732,12 @@ you can have a look at our [guide on distinct](https://www.algolia.com/doc/searc
1617
1732
  If set to true,
1618
1733
  the result hits will contain ranking information in the **_rankingInfo** attribute.
1619
1734
 
1620
- #### numericAttributesToIndex
1735
+ #### numericAttributesForFiltering
1621
1736
 
1622
1737
  - scope: `settings`
1623
1738
  - type: `array of strings`
1624
1739
  - default: ``
1740
+ - formerly known as: `numericAttributesToIndex`
1625
1741
 
1626
1742
 
1627
1743
  All numerical attributes are automatically indexed as numerical filters
@@ -1727,6 +1843,33 @@ For example, `[["category:Book","category:Movie"],"author:John%20Doe"]`.
1727
1843
 
1728
1844
  If set to false, this query will not be taken into account in the analytics feature.
1729
1845
 
1846
+ #### analyticsTags
1847
+
1848
+ - scope: `search`
1849
+ - type: `array of strings`
1850
+ - default: `null`
1851
+
1852
+
1853
+ If set, tag your query with the specified identifiers. Tags can then be used in the Analytics to analyze a subset of searches only.
1854
+
1855
+ #### synonyms
1856
+
1857
+ - scope: `search`
1858
+ - type: `boolean`
1859
+ - default: `true`
1860
+
1861
+
1862
+ If set to `false`, the search will not use the synonyms defined for the targeted index.
1863
+
1864
+ #### replaceSynonymsInHighlight
1865
+
1866
+ - scope: `search`, `settings`
1867
+ - type: `boolean`
1868
+ - default: `true`
1869
+
1870
+
1871
+ If set to `false`, words matched via synonym expansion will not be replaced by the matched synonym in the highlighted result.
1872
+
1730
1873
  #### placeholders
1731
1874
 
1732
1875
  - scope: `settings`
@@ -1774,6 +1917,19 @@ For example:
1774
1917
  ]
1775
1918
  ```
1776
1919
 
1920
+ #### minProximity
1921
+
1922
+ - scope: `search`, `settings`
1923
+ - type: `integer`
1924
+ - default: `1`
1925
+
1926
+
1927
+ Configure the precision of the `proximity` ranking criterion. By default, the minimum (and best) proximity value distance between 2 matching words is 1. Setting it to 2 (or 3) would allow 1 (or 2) words to be found between the matching words without degrading the proximity ranking value.
1928
+
1929
+ Considering the query *“javascript framework”*, if you set `minProximity=2`, the records *“JavaScript framework”* and *“JavaScript charting framework”* will get the same proximity score, even if the second contains a word between the two matching words.
1930
+
1931
+ **Note:** the maximum `minProximity` that can be set is 7. Any higher value will disable the `proximity` criterion from the ranking formula.
1932
+
1777
1933
 
1778
1934
  ## Manage Indices
1779
1935
 
@@ -1845,7 +2001,7 @@ The move_index method will overwrite the destination index, and delete the tempo
1845
2001
  **Warning**
1846
2002
 
1847
2003
  The move_index operation will override all settings of the destination,
1848
- There is one exception for the [slaves](#slaves) parameter which is not impacted.
2004
+ There is one exception for the [replicas](#replicas) parameter which is not impacted.
1849
2005
 
1850
2006
  For example, if you want to fully update your index `MyIndex` every night, we recommend the following process:
1851
2007
 
@@ -1853,13 +2009,13 @@ For example, if you want to fully update your index `MyIndex` every night, we re
1853
2009
  and [Get synonym](#get-synonym---get_synonym).
1854
2010
  1. Apply settings and synonyms to the temporary index `MyTmpIndex`, (this will create the `MyTmpIndex` index)
1855
2011
  using [Set settings](#set-settings---set_settings) and [Batch synonyms](#batch-synonyms---batch_synonyms)
1856
- (make sure to remove the [slaves](#slaves) parameter from the settings if it exists).
2012
+ (make sure to remove the [replicas](#replicas) parameter from the settings if it exists).
1857
2013
  1. Import your records into a new index using [Add objects](#add-objects---add_objects).
1858
2014
  1. Atomically replace the index `MyIndex` with the content and settings of the index `MyTmpIndex`
1859
2015
  using the [Move index](#move-index---move_index) method.
1860
2016
  This will automatically override the old index without any downtime on the search.
1861
2017
  1. You'll end up with only one index called `MyIndex`, that contains the records and settings pushed to `MyTmpIndex`
1862
- and the slave-indices that were initially attached to `MyIndex` will be in sync with the new data.
2018
+ and the replica-indices that were initially attached to `MyIndex` will be in sync with the new data.
1863
2019
 
1864
2020
 
1865
2021
 
@@ -1868,22 +2024,57 @@ For example, if you want to fully update your index `MyIndex` every night, we re
1868
2024
 
1869
2025
  ## Api Keys
1870
2026
 
1871
- The **admin** API key provides full control of all your indices. *The admin API key should always be kept secure; do NOT use it from outside your back-end.*
2027
+ ### Overview
2028
+
2029
+ When creating your Algolia Account, you'll notice there are 3 different API Keys:
2030
+
2031
+ - **Admin API Key** - it provides full control of all your indices.
2032
+ *The admin API key should always be kept secure;
2033
+ do NOT give it to anybody; do NOT use it from outside your back-end as it will
2034
+ allow the person who has it to query/change/delete data*
2035
+
2036
+ - **Search-Only API Key** - It allows you to search on every indices.
2037
+
2038
+ - **Monitoring API Key** - It allows you to access the [Monitoring API](https://www.algolia.com/doc/rest-api/monitoring)
2039
+
2040
+ #### Other types of API keys
2041
+
2042
+ The *Admin API Key* and *Search-Only API Key* both have really large scope and sometimes you want to give a key to
2043
+ someone that have restricted permissions, can it be an index, a rate limit, a validity limit, ...
2044
+
2045
+ To address those use-cases we have two differents type of keys:
1872
2046
 
1873
- You can also generate user API keys to control security.
1874
- These API keys can be restricted to a set of operations or/and restricted to a given index.
2047
+ - **Secured API Keys**
2048
+
2049
+ When you need to restrict the scope of the *Search Key*, we recommend to use *Secured API Key*.
2050
+ You can generate them on the fly (without any call to the API)
2051
+ from the *Search Only API Key* or any search *User Key* using the [Generate key](#generate-key---generate_secured_api_key) method
2052
+
2053
+ - **User API Keys**
2054
+
2055
+ If *Secured API Keys* does not meet your requirements, you can make use of *User keys*.
2056
+ Managing and especially creating those keys requires a call to the API.
2057
+
2058
+ We have several methods to manage them:
2059
+ - [Add user key](#add-user-key---add_user_key)
2060
+ - [Update user key](#update-user-key---update_user_key)
2061
+ - [Delete user key](#delete-user-key---delete_user_key)
2062
+ - [List api keys](#list-api-keys---list_api_keys)
2063
+ - [Get key permissions](#get-key-permissions---get_user_key_acl)
1875
2064
 
1876
2065
  ### Generate key - `generate_secured_api_key`
1877
2066
 
1878
- You may have a single index containing **per user** data. In that case, all records should be tagged with their associated `user_id` in order to add a `tagFilters=user_42` filter at query time to retrieve only what a user has access to. If you're using the [JavaScript client](http://github.com/algolia/algoliasearch-client-js), it will result in a security breach since the user is able to modify the `tagFilters` you've set by modifying the code from the browser. To keep using the JavaScript client (recommended for optimal latency) and target secured records, you can generate a secured API key from your backend:
2067
+ When you need to restrict the scope of the *Search Key*, we recommend to use *Secured API Key*.
2068
+ You can generate a *Secured API Key* from the *Search Only API Key* or any search *User API Key*
1879
2069
 
1880
- ```ruby
1881
- # generate a public API key for user 42. Here, records are tagged with:
1882
- # - 'user_XXXX' if they are visible by user XXXX
1883
- public_key = Algolia.generate_secured_api_key 'YourSearchOnlyApiKey', {'filters'=> '_tags:user_42'}
1884
- ```
2070
+ There is a few things to know about about *Secured API Keys*
2071
+ - They always need to be generated **on your backend** using one of our API Client
2072
+ - You can generate them on the fly (without any call to the API)
2073
+ - They will not appear on the dashboard as they are generated without any call to the API
2074
+ - The key you use to generate it **needs to become private** and you should not use it in your frontend.
2075
+ - The generated secured API key **will inherit any restriction from the search key it has been generated from**
1885
2076
 
1886
- This public API key can then be used in your JavaScript code as follow:
2077
+ You can then use the key in your frontend code
1887
2078
 
1888
2079
  ```js
1889
2080
  var client = algoliasearch('YourApplicationID', '<%= public_api_key %>');
@@ -1900,29 +2091,84 @@ index.search('something', function(err, content) {
1900
2091
  });
1901
2092
  ```
1902
2093
 
1903
- 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.
2094
+ #### Filters
2095
+
2096
+ Every filter set in the API key will always be applied. On top of that [filters](#filters) can be applied
2097
+ in the query parameters.
1904
2098
 
1905
2099
  ```ruby
1906
2100
  # generate a public API key for user 42. Here, records are tagged with:
1907
2101
  # - 'user_XXXX' if they are visible by user XXXX
1908
- public_key = Algolia.generate_secured_api_key 'YourSearchOnlyApiKey', {'filters'=> '_tags:user_42', 'userToken'=> 'user_42'}
2102
+ public_key = Algolia.generate_secured_api_key 'YourSearchOnlyApiKey', {'filters'=> '_tags:user_42'}
1909
2103
  ```
1910
2104
 
1911
- This public API key can then be used in your JavaScript code as follow:
2105
+ **Warning**:
1912
2106
 
1913
- ```js
1914
- var client = algoliasearch('YourApplicationID', '<%= public_api_key %>');
2107
+ If you set filters in the key `groups:admin`, and `groups:press OR groups:visitors` in the query parameters,
2108
+ this will be equivalent to `groups:admin AND (groups:press OR groups:visitors)`
1915
2109
 
1916
- var index = client.initIndex('indexName')
2110
+ ##### Having one API Key per User
1917
2111
 
1918
- index.search('another query', function(err, content) {
1919
- if (err) {
1920
- console.error(err);
1921
- return;
1922
- }
2112
+ One of the usage of secured API keys, is to have allow users to see only part of an index, when this index
2113
+ contains the data of all users.
2114
+ In that case, you can tag all records with their associated `user_id` in order to add a `user_id=42` filter when
2115
+ generating the *Secured API Key* to retrieve only what a user is tagged in.
1923
2116
 
1924
- console.log(content);
1925
- });
2117
+ **Warning**
2118
+ If you're generating *Secured API Keys* using the [JavaScript client](http://github.com/algolia/algoliasearch-client-js) in your frontend,
2119
+ it will result in a security breach since the user is able to modify the `tagFilters` you've set
2120
+ by modifying the code from the browser.
2121
+
2122
+ #### Valid Until
2123
+
2124
+ You can set a Unix timestamp used to define the expiration date of the API key
2125
+
2126
+ ```ruby
2127
+ # generate a public API key that is valid for 1 hour:
2128
+ valid_until = Time.now.to_i + 3600
2129
+ public_key = Algolia.generate_secured_api_key 'YourSearchOnlyApiKey', {'validUntil'=> valid_until}
2130
+ ```
2131
+
2132
+ #### Index Restriction
2133
+
2134
+ You can restrict the key to a list of index names allowed for the secured API key
2135
+
2136
+ ```ruby
2137
+ # generate a public API key that is restricted to 'index1' and 'index2':
2138
+ public_key = Algolia.generate_secured_api_key 'YourSearchOnlyApiKey', {'restrictIndices'=> 'index1,index2'}
2139
+ ```
2140
+
2141
+ #### Rate Limiting
2142
+
2143
+ If you want to rate limit a secured API Key, the API key you generate the secured api key from need to be rate-limited.
2144
+ You can do that either via the dashboard or via the API using the
2145
+ [Add user key](#add-user-key---add_user_key) or [Update user key](#update-user-key---update_user_key) method
2146
+
2147
+ ##### User Rate Limiting
2148
+
2149
+ By default the rate limits will only use the `IP`.
2150
+
2151
+ This can be an issue when several of your end users are using the same IP.
2152
+ To avoid that, you can set a `userToken` query parameter when generating the key.
2153
+
2154
+ When set, a unique user will be identified by his `IP + user_token` instead of only by his `IP`.
2155
+
2156
+ This allows you to restrict a single user to performing a maximum of `N` API calls per hour,
2157
+ even if he shares his `IP` with another user.
2158
+
2159
+ ```ruby
2160
+ # generate a public API key for user 42. Here, records are tagged with:
2161
+ # - 'user_XXXX' if they are visible by user XXXX
2162
+ public_key = Algolia.generate_secured_api_key 'YourSearchOnlyApiKey', {'filters'=> '_tags:user_42', 'userToken'=> 'user_42'}
2163
+ ```
2164
+
2165
+ #### Network restriction
2166
+
2167
+ For more protection against API key leaking and reuse you can restrict the key to be valid only from specific IPv4 networks
2168
+
2169
+ ```ruby
2170
+ # generate a public API key that is restricted to '192.168.1.0/24':
2171
+ public_key = Algolia.generate_secured_api_key 'YourSearchOnlyApiKey', {'restrictSources'=> '192.168.1.0/24'}
1926
2172
  ```
1927
2173
 
1928
2174
 
@@ -1935,7 +2181,7 @@ index.search('another query', function(err, content) {
1935
2181
 
1936
2182
  This method saves a single synonym record into the index.
1937
2183
 
1938
- In this example, we specify true to forward the creation to slave indices.
2184
+ In this example, we specify true to forward the creation to replica indices.
1939
2185
  By default the behavior is to save only on the specified index.
1940
2186
 
1941
2187
  ```ruby
@@ -1949,7 +2195,7 @@ index.save_synonym('a-unique-identifier', {
1949
2195
  ### Batch synonyms - `batch_synonyms`
1950
2196
 
1951
2197
  Use the batch method to create a large number of synonyms at once,
1952
- forward them to slave indices if desired,
2198
+ forward them to replica indices if desired,
1953
2199
  and optionally replace all existing synonyms
1954
2200
  on the index with the content of the batch using the replaceExistingSynonyms parameter.
1955
2201
 
@@ -1958,7 +2204,7 @@ on a production index. This is the only way to ensure the index always
1958
2204
  has a full list of synonyms to use during the indexing of the new list.
1959
2205
 
1960
2206
  ```ruby
1961
- # Batch synonyms, with slave forwarding and atomic replacement of existing synonyms
2207
+ # Batch synonyms, with replica forwarding and atomic replacement of existing synonyms
1962
2208
  index.batch_synonyms([{
1963
2209
  :objectID => 'a-unique-identifier',
1964
2210
  :type => 'synonym',
@@ -1985,10 +2231,10 @@ in the batch update.
1985
2231
 
1986
2232
  Use the normal index delete method to delete synonyms,
1987
2233
  specifying the objectID of the synonym record you want to delete.
1988
- Forward the deletion to slave indices by setting the forwardToSlaves parameter to true.
2234
+ Forward the deletion to replica indices by setting the forwardToReplicas parameter to true.
1989
2235
 
1990
2236
  ```ruby
1991
- # Delete and forward to slaves
2237
+ # Delete and forward to replicas
1992
2238
  index.delete_synonym('a-unique-identifier', true)
1993
2239
  ```
1994
2240
 
@@ -2003,7 +2249,7 @@ To atomically replace all synonyms of an index,
2003
2249
  use the batch method with the replaceExistingSynonyms parameter set to true.
2004
2250
 
2005
2251
  ```ruby
2006
- # Clear synonyms and forward to slaves
2252
+ # Clear synonyms and forward to replicas
2007
2253
  index.clear_synonyms(true)
2008
2254
  ```
2009
2255
 
@@ -2042,47 +2288,6 @@ results = index.search_synonyms('street', {
2042
2288
  ### Custom batch - `batch`
2043
2289
 
2044
2290
  You may want to perform multiple operations with one API call to reduce latency.
2045
- We expose four methods to perform batch operations:
2046
-
2047
- * Add objects - `add_objects`: Add an array of objects using automatic `objectID` assignment.
2048
- * Update objects - `save_objects`: Add or update an array of objects that contains an `objectID` attribute.
2049
- * Delete objects - `delete_objects`: Delete an array of objectIDs.
2050
- * Partial update - `partial_update_objects`: Partially update an array of objects that contain an `objectID` attribute (only specified attributes will be updated).
2051
-
2052
- Example using automatic `objectID` assignment:
2053
-
2054
- ```ruby
2055
- res = index.add_objects([{"firstname" => "Jimmie",
2056
- "lastname" => "Barninger"},
2057
- {"firstname" => "Warren",
2058
- "lastname" => "Speach"}])
2059
- ```
2060
-
2061
- Example with user defined `objectID` (add or update):
2062
-
2063
- ```ruby
2064
- res = index.save_objects([{"firstname" => "Jimmie",
2065
- "lastname" => "Barninger",
2066
- "objectID" => "myID1"},
2067
- {"firstname" => "Warren",
2068
- "lastname" => "Speach",
2069
- "objectID" => "myID2"}])
2070
- ```
2071
-
2072
- Example that deletes a set of records:
2073
-
2074
- ```ruby
2075
- res = index.delete_objects(["myID1", "myID2"])
2076
- ```
2077
-
2078
- Example that updates only the `firstname` attribute:
2079
-
2080
- ```ruby
2081
- res = index.partial_update_objects([{"firstname" => "Jimmie",
2082
- "objectID" => "SFO"},
2083
- {"firstname" => "Warren",
2084
- "objectID" => "myID2"}])
2085
- ```
2086
2291
 
2087
2292
 
2088
2293
 
@@ -2400,41 +2605,6 @@ Algolia.get_user_key("f420238212c54dcfad07ea0aa6d5c45f")
2400
2605
  index.get_user_key("71671c38001bf3ac857bc82052485107")
2401
2606
  ```
2402
2607
 
2403
- ### Multiple queries - `multiple_queries`
2404
-
2405
- You can send multiple queries with a single API call using a batch of queries:
2406
-
2407
- ```ruby
2408
- # perform 3 queries in a single API call:
2409
- # - 1st query targets index `categories`
2410
- # - 2nd and 3rd queries target index `products`
2411
- res = Algolia.multiple_queries([{:index_name => "categories", "query" => my_query_string, "hitsPerPage" => 3}
2412
- , {:index_name => "products", "query" => my_query_string, "hitsPerPage" => 3, "filters" => "_tags:promotion"}
2413
- , {:index_name => "products", "query" => my_query_string, "hitsPerPage" => 10}])
2414
-
2415
- puts res["results"]
2416
- ```
2417
-
2418
- You can specify a `strategy` parameter to optimize your multiple queries:
2419
-
2420
- - `none`: Execute the sequence of queries until the end.
2421
- - `stopIfEnoughMatches`: Execute the sequence of queries until the number of hits is reached by the sum of hits.
2422
-
2423
- #### Response
2424
-
2425
- The resulting JSON contains the following fields:
2426
-
2427
- - `results` (array): The results for each request, in the order they were submitted. The contents are the same as in [Search in an index](#search-in-an-index---search).
2428
-
2429
- Each result also includes the following additional fields:
2430
-
2431
- - `index` (string): The name of the targeted index.
2432
-
2433
- - `processed` (boolean, optional): *Note: Only returned when `strategy` is `stopIfEnoughmatches`.* Whether the query was processed.
2434
-
2435
-
2436
-
2437
-
2438
2608
  ### Get Logs - `get_logs`
2439
2609
 
2440
2610
  You can retrieve the latest logs via this API. Each log entry contains:
@@ -50,17 +50,17 @@ Gem::Specification.new do |s|
50
50
  s.specification_version = 4
51
51
 
52
52
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
53
- s.add_runtime_dependency(%q<httpclient>, ["~> 2.8.2"])
53
+ s.add_runtime_dependency(%q<httpclient>, ["~> 2.8.2.4"])
54
54
  s.add_runtime_dependency(%q<json>, [">= 1.5.1"])
55
55
  s.add_development_dependency "travis"
56
56
  s.add_development_dependency "rake"
57
57
  s.add_development_dependency "rdoc"
58
58
  else
59
- s.add_dependency(%q<httpclient>, ["~> 2.8.2"])
59
+ s.add_dependency(%q<httpclient>, ["~> 2.8.2.4"])
60
60
  s.add_dependency(%q<json>, [">= 1.5.1"])
61
61
  end
62
62
  else
63
- s.add_dependency(%q<httpclient>, ["~> 2.8.2"])
63
+ s.add_dependency(%q<httpclient>, ["~> 2.8.2.4"])
64
64
  s.add_dependency(%q<json>, [">= 1.5.1"])
65
65
  end
66
66
  end
@@ -349,6 +349,7 @@ module Algolia
349
349
  rescue => e
350
350
  exceptions << e
351
351
  end
352
+ host[:session].reset_all
352
353
  end
353
354
  raise AlgoliaProtocolError.new(0, "Cannot reach any host: #{exceptions.map { |e| e.to_s }.join(', ')}")
354
355
  end
data/lib/algolia/index.rb CHANGED
@@ -208,9 +208,10 @@ module Algolia
208
208
  # Get an object from this index
209
209
  #
210
210
  # @param objectID the unique identifier of the object to retrieve
211
- # @param attributesToRetrieve (optional) if set, contains the list of attributes to retrieve as a string separated by ","
211
+ # @param attributesToRetrieve (optional) if set, contains the list of attributes to retrieve as an array of strings of a string separated by ","
212
212
  #
213
213
  def get_object(objectID, attributesToRetrieve = nil)
214
+ attributesToRetrieve = attributesToRetrieve.join(',') if attributesToRetrieve.is_a?(Array)
214
215
  if attributesToRetrieve.nil?
215
216
  client.get(Protocol.object_uri(name, objectID, nil), :read)
216
217
  else
@@ -222,9 +223,16 @@ module Algolia
222
223
  # Get a list of objects from this index
223
224
  #
224
225
  # @param objectIDs the array of unique identifier of the objects to retrieve
225
- #
226
- def get_objects(objectIDs)
227
- client.post(Protocol.objects_uri, { :requests => objectIDs.map { |objectID| { :indexName => name, :objectID => objectID } } }.to_json, :read)['results']
226
+ # @param attributesToRetrieve (optional) if set, contains the list of attributes to retrieve as an array of strings of a string separated by ","
227
+ #
228
+ def get_objects(objectIDs, attributesToRetrieve = nil)
229
+ attributesToRetrieve = attributesToRetrieve.join(',') if attributesToRetrieve.is_a?(Array)
230
+ requests = objectIDs.map do |objectID|
231
+ req = {:indexName => name, :objectID => objectID.to_s}
232
+ req[:attributesToRetrieve] = attributesToRetrieve unless attributesToRetrieve.nil?
233
+ req
234
+ end
235
+ client.post(Protocol.objects_uri, { :requests => requests }.to_json, :read)['results']
228
236
  end
229
237
 
230
238
  # Wait the publication of a task on the server.
@@ -555,6 +563,20 @@ module Algolia
555
563
  res
556
564
  end
557
565
 
566
+ # Search in facets
567
+ #
568
+ # @param facet Name of the facet to search. It must have been declared in the
569
+ # index's`attributesForFaceting` setting with the `searchable()` modifier.
570
+ # @param text Text to search for in the facet's values
571
+ # @param query An optional query to take extra search parameters into account.
572
+ # These parameters apply to index objects like in a regular search query.
573
+ # Only facet values contained in the matched objects will be returned.
574
+ def search_facet(facet, text, query = {})
575
+ params = query.clone
576
+ params['facetQuery'] = text
577
+ client.post(Protocol.search_facet_uri(name, facet), params.to_json)
578
+ end
579
+
558
580
  # Perform a search with disjunctive facets generating as many queries as number of disjunctive facets
559
581
  #
560
582
  # @param query the query
@@ -675,17 +697,17 @@ module Algolia
675
697
  # Delete a synonym
676
698
  #
677
699
  # @param objectID the synonym objectID
678
- # @param forward_to_slaves should we forward the delete to slave indices
679
- def delete_synonym(objectID, forward_to_slaves = false)
680
- client.delete("#{Protocol.synonym_uri(name, objectID)}?forwardToSlaves=#{forward_to_slaves}", :write)
700
+ # @param forward_to_replicas should we forward the delete to replica indices
701
+ def delete_synonym(objectID, forward_to_replicas = false)
702
+ client.delete("#{Protocol.synonym_uri(name, objectID)}?forwardToReplicas=#{forward_to_replicas}", :write)
681
703
  end
682
704
 
683
705
  # Delete a synonym and wait the end of indexing
684
706
  #
685
707
  # @param objectID the synonym objectID
686
- # @param forward_to_slaves should we forward the delete to slave indices
687
- def delete_synonym!(objectID, forward_to_slaves = false)
688
- res = delete_synonym(objectID, forward_to_slaves)
708
+ # @param forward_to_replicas should we forward the delete to replica indices
709
+ def delete_synonym!(objectID, forward_to_replicas = false)
710
+ res = delete_synonym(objectID, forward_to_replicas)
689
711
  wait_task(res["taskID"])
690
712
  return res
691
713
  end
@@ -694,34 +716,34 @@ module Algolia
694
716
  #
695
717
  # @param objectID the synonym objectID
696
718
  # @param synonym the synonym
697
- # @param forward_to_slaves should we forward the delete to slave indices
698
- def save_synonym(objectID, synonym, forward_to_slaves = false)
699
- client.put("#{Protocol.synonym_uri(name, objectID)}?forwardToSlaves=#{forward_to_slaves}", synonym.to_json, :write)
719
+ # @param forward_to_replicas should we forward the delete to replica indices
720
+ def save_synonym(objectID, synonym, forward_to_replicas = false)
721
+ client.put("#{Protocol.synonym_uri(name, objectID)}?forwardToReplicas=#{forward_to_replicas}", synonym.to_json, :write)
700
722
  end
701
723
 
702
724
  # Save a synonym and wait the end of indexing
703
725
  #
704
726
  # @param objectID the synonym objectID
705
727
  # @param synonym the synonym
706
- # @param forward_to_slaves should we forward the delete to slave indices
707
- def save_synonym!(objectID, synonym, forward_to_slaves = false)
708
- res = save_synonym(objectID, synonym, forward_to_slaves)
728
+ # @param forward_to_replicas should we forward the delete to replica indices
729
+ def save_synonym!(objectID, synonym, forward_to_replicas = false)
730
+ res = save_synonym(objectID, synonym, forward_to_replicas)
709
731
  wait_task(res["taskID"])
710
732
  return res
711
733
  end
712
734
 
713
735
  # Clear all synonyms
714
736
  #
715
- # @param forward_to_slaves should we forward the delete to slave indices
716
- def clear_synonyms(forward_to_slaves = false)
717
- client.post("#{Protocol.clear_synonyms_uri(name)}?forwardToSlaves=#{forward_to_slaves}", :write)
737
+ # @param forward_to_replicas should we forward the delete to replica indices
738
+ def clear_synonyms(forward_to_replicas = false)
739
+ client.post("#{Protocol.clear_synonyms_uri(name)}?forwardToReplicas=#{forward_to_replicas}", :write)
718
740
  end
719
741
 
720
742
  # Clear all synonyms and wait the end of indexing
721
743
  #
722
- # @param forward_to_slaves should we forward the delete to slave indices
723
- def clear_synonyms!(forward_to_slaves = false)
724
- res = clear_synonyms(forward_to_slaves)
744
+ # @param forward_to_replicas should we forward the delete to replica indices
745
+ def clear_synonyms!(forward_to_replicas = false)
746
+ res = clear_synonyms(forward_to_replicas)
725
747
  wait_task(res["taskID"])
726
748
  return res
727
749
  end
@@ -729,19 +751,19 @@ module Algolia
729
751
  # Add/Update an array of synonyms
730
752
  #
731
753
  # @param synonyms the array of synonyms to add/update
732
- # @param forward_to_slaves should we forward the delete to slave indices
754
+ # @param forward_to_replicas should we forward the delete to replica indices
733
755
  # @param replace_existing_synonyms should we replace the existing synonyms before adding the new ones
734
- def batch_synonyms(synonyms, forward_to_slaves = false, replace_existing_synonyms = false)
735
- client.post("#{Protocol.batch_synonyms_uri(name)}?forwardToSlaves=#{forward_to_slaves}&replaceExistingSynonyms=#{replace_existing_synonyms}", synonyms.to_json, :batch)
756
+ def batch_synonyms(synonyms, forward_to_replicas = false, replace_existing_synonyms = false)
757
+ client.post("#{Protocol.batch_synonyms_uri(name)}?forwardToReplicas=#{forward_to_replicas}&replaceExistingSynonyms=#{replace_existing_synonyms}", synonyms.to_json, :batch)
736
758
  end
737
759
 
738
760
  # Add/Update an array of synonyms and wait the end of indexing
739
761
  #
740
762
  # @param synonyms the array of synonyms to add/update
741
- # @param forward_to_slaves should we forward the delete to slave indices
763
+ # @param forward_to_replicas should we forward the delete to replica indices
742
764
  # @param replace_existing_synonyms should we replace the existing synonyms before adding the new ones
743
- def batch_synonyms!(synonyms, forward_to_slaves = false, replace_existing_synonyms = false)
744
- res = batch_synonyms(synonyms, forward_to_slaves, replace_existing_synonyms)
765
+ def batch_synonyms!(synonyms, forward_to_replicas = false, replace_existing_synonyms = false)
766
+ res = batch_synonyms(synonyms, forward_to_replicas, replace_existing_synonyms)
745
767
  wait_task(res["taskID"])
746
768
  return res
747
769
  end
@@ -83,6 +83,10 @@ module Algolia
83
83
  "#{index_uri(index)}/browse#{params}"
84
84
  end
85
85
 
86
+ def Protocol.search_facet_uri(index, facet)
87
+ "#{index_uri(index)}/facets/#{facet}/query"
88
+ end
89
+
86
90
  def Protocol.partial_object_uri(index, object_id, create_if_not_exits = true)
87
91
  params = create_if_not_exits ? "" : "?createIfNotExists=false"
88
92
  "#{index_uri(index)}/#{CGI.escape(object_id)}/partial#{params}"
@@ -1,3 +1,3 @@
1
1
  module Algolia
2
- VERSION = "1.11.0"
2
+ VERSION = "1.12.0"
3
3
  end
data/spec/client_spec.rb CHANGED
@@ -187,6 +187,26 @@ describe 'Client' do
187
187
  objects.size.should eq(2)
188
188
  end
189
189
 
190
+ it "should restrict attributesToRetrieve" do
191
+ @index.clear_index
192
+ @index.add_object({:firstname => "Robert", :lastname => "foo", :objectID => 1})
193
+ @index.add_object!({:firstname => "Robert2", :lastname => "bar", :objectID => 2})
194
+ objects = @index.get_objects([1, 2], ['firstname'])
195
+ objects.size.should eq(2)
196
+ objects[0].should eq({"firstname"=>"Robert", "objectID"=>"1"})
197
+ objects[1].should eq({"firstname"=>"Robert2", "objectID"=>"2"})
198
+
199
+ objects = @index.get_objects([1, 2], [:firstname])
200
+ objects.size.should eq(2)
201
+ objects[0].should eq({"firstname"=>"Robert", "objectID"=>"1"})
202
+ objects[1].should eq({"firstname"=>"Robert2", "objectID"=>"2"})
203
+
204
+ objects = @index.get_objects(["1", "2"], 'firstname,lastname')
205
+ objects.size.should eq(2)
206
+ objects[0].should eq({"firstname"=>"Robert", "lastname"=>"foo", "objectID"=>"1"})
207
+ objects[1].should eq({"firstname"=>"Robert2", "lastname"=>"bar", "objectID"=>"2"})
208
+ end
209
+
190
210
  it "should delete the object" do
191
211
  @index.clear
192
212
  @index.add_object!({:firstname => "Robert"})
@@ -769,6 +789,64 @@ describe 'Client' do
769
789
  res['results'][0]['params'].should be_a(String)
770
790
  end
771
791
 
792
+ it 'should handle facet search' do
793
+ objects = {
794
+ :snoopy => {
795
+ :objectID => '1',
796
+ 'name' => 'Snoopy',
797
+ :kind => ['dog', 'animal'],
798
+ :born => 1950,
799
+ :series => 'Peanuts'
800
+ },
801
+ :woodstock => {
802
+ :objectID => '2',
803
+ :name => 'Woodstock',
804
+ :kind => ['bird', 'animal'],
805
+ :born => 1960,
806
+ :series => 'Peanuts'
807
+ },
808
+ :charlie => {
809
+ :objectID => '3',
810
+ :name => 'Charlie Brown',
811
+ :kind => ['human'],
812
+ :born => 1950,
813
+ :series => 'Peanuts'
814
+ },
815
+ :hobbes => {
816
+ :objectID => '4',
817
+ :name => 'Hobbes',
818
+ :kind => ['tiger', 'animal', 'teddy'],
819
+ :born => 1985,
820
+ :series => 'Calvin & Hobbes'
821
+ },
822
+ :calvin => {
823
+ :objectID => '5',
824
+ :name => 'Calvin',
825
+ :kind => ['human'],
826
+ :born => 1985,
827
+ :series => 'Calvin & Hobbes'
828
+ }
829
+ }
830
+
831
+ index = Algolia::Index.new(safe_index_name('test_facet_search'))
832
+ index.set_settings({
833
+ :attributesForFaceting => [
834
+ 'searchable(series)',
835
+ 'kind'
836
+ ]
837
+ })
838
+ index.add_objects! objects.values
839
+
840
+ query = {
841
+ :facetFilters => ['kind:animal'],
842
+ :numericFilters => ['born >= 1955']
843
+ }
844
+ answer = index.search_facet 'series', 'Peanutz', query
845
+ expect(answer['facetHits'].size).to eq(1)
846
+ expect(answer['facetHits'].first['value']).to eq('Peanuts')
847
+ expect(answer['facetHits'].first['count']).to eq(1)
848
+ end
849
+
772
850
  it 'should handle disjunctive faceting' do
773
851
  index = Algolia::Index.new(safe_index_name("test_hotels"))
774
852
  index.set_settings :attributesForFacetting => ['city', 'stars', 'facilities']
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.11.0
4
+ version: 1.12.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Algolia
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-21 00:00:00.000000000 Z
11
+ date: 2016-10-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httpclient
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: 2.8.2
19
+ version: 2.8.2.4
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: 2.8.2
26
+ version: 2.8.2.4
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: json
29
29
  requirement: !ruby/object:Gem::Requirement