@@ -135,6 +135,30 @@ public JSONObject searchSync(@NonNull Query query) throws AlgoliaException {
135
135
return search (query );
136
136
}
137
137
138
+ /**
139
+ * Run multiple queries on this index with one API call.
140
+ * A variant of {@link Client#multipleQueriesAsync(List, Client.MultipleQueriesStrategy, CompletionHandler)}
141
+ * where the targeted index is always the receiver.
142
+ *
143
+ * @param queries The queries to run.
144
+ * @param strategy The strategy to use.
145
+ * @param completionHandler The listener that will be notified of the request's outcome.
146
+ * @return A cancellable request.
147
+ */
148
+ public Request multipleQueriesAsync (final @ NonNull List <Query > queries , final Client .MultipleQueriesStrategy strategy , @ NonNull CompletionHandler completionHandler ) {
149
+ final List <Query > queriesCopy = new ArrayList <>(queries .size ());
150
+ for (Query query : queries ) {
151
+ queriesCopy .add (new Query (query ));
152
+ }
153
+ return getClient ().new AsyncTaskRequest (completionHandler ) {
154
+ @ NonNull
155
+ @ Override
156
+ JSONObject run () throws AlgoliaException {
157
+ return multipleQueries (queriesCopy , strategy == null ? null : strategy .toString ());
158
+ }
159
+ }.start ();
160
+ }
161
+
138
162
/**
139
163
* Search inside this index synchronously.
140
164
*
@@ -153,20 +177,22 @@ protected byte[] searchSyncRaw(@NonNull Query query) throws AlgoliaException {
153
177
* @param completionHandler The listener that will be notified of the request's outcome.
154
178
* @return A cancellable request.
155
179
*/
156
- public Request searchDisjunctiveFacetingAsync (@ NonNull Query query , @ NonNull List <String > disjunctiveFacets , @ NonNull Map <String , List <String >> refinements , @ NonNull CompletionHandler completionHandler ) {
157
- final Query queryCopy = new Query (query );
158
- final List <String > disjunctiveFacetsCopy = new ArrayList <>(disjunctiveFacets );
159
- final Map <String , List <String >> refinementsCopy = new HashMap <>();
160
- for (Map .Entry <String , List <String >> entry : refinements .entrySet ()) {
161
- refinementsCopy .put (entry .getKey (), new ArrayList <String >(entry .getValue ()));
162
- }
163
- return getClient ().new AsyncTaskRequest (completionHandler ) {
164
- @ NonNull
180
+ public Request searchDisjunctiveFacetingAsync (@ NonNull Query query , @ NonNull final List <String > disjunctiveFacets , @ NonNull final Map <String , List <String >> refinements , @ NonNull final CompletionHandler completionHandler ) {
181
+ final List <Query > queries = computeDisjunctiveFacetingQueries (query , disjunctiveFacets , refinements );
182
+ return multipleQueriesAsync (queries , null , new CompletionHandler () {
165
183
@ Override
166
- JSONObject run () throws AlgoliaException {
167
- return searchDisjunctiveFaceting (queryCopy , disjunctiveFacetsCopy , refinementsCopy );
184
+ public void requestCompleted (JSONObject content , AlgoliaException error ) {
185
+ JSONObject aggregatedResults = null ;
186
+ try {
187
+ if (content != null ) {
188
+ aggregatedResults = aggregateDisjunctiveFacetingResults (content , disjunctiveFacets , refinements );
189
+ }
190
+ } catch (AlgoliaException e ) {
191
+ error = e ;
192
+ }
193
+ completionHandler .requestCompleted (aggregatedResults , error );
168
194
}
169
- }. start ( );
195
+ });
170
196
}
171
197
172
198
/**
@@ -957,25 +983,38 @@ protected JSONObject clearIndex() throws AlgoliaException {
957
983
}
958
984
959
985
/**
960
- * Perform a search with disjunctive facets generating as many queries as number of disjunctive facets
986
+ * Filter disjunctive refinements from generic refinements and a list of disjunctive facets.
961
987
*
962
- * @param query the query
963
988
* @param disjunctiveFacets the array of disjunctive facets
964
989
* @param refinements Map representing the current refinements
965
- * @throws AlgoliaException
990
+ * @return The disjunctive refinements
966
991
*/
967
- protected JSONObject searchDisjunctiveFaceting ( @ NonNull Query query , @ NonNull List <String > disjunctiveFacets , @ NonNull Map <String , List <String >> refinements ) throws AlgoliaException {
968
- // Retain only refinements corresponding to the disjunctive facets.
992
+ private @ NonNull Map < String , List < String >> computeDisjunctiveRefinements ( @ NonNull List <String > disjunctiveFacets , @ NonNull Map <String , List <String >> refinements )
993
+ {
969
994
Map <String , List <String >> disjunctiveRefinements = new HashMap <>();
970
995
for (Map .Entry <String , List <String >> elt : refinements .entrySet ()) {
971
996
if (disjunctiveFacets .contains (elt .getKey ())) {
972
997
disjunctiveRefinements .put (elt .getKey (), elt .getValue ());
973
998
}
974
999
}
1000
+ return disjunctiveRefinements ;
1001
+ }
1002
+
1003
+ /**
1004
+ * Compute the queries to run to implement disjunctive faceting.
1005
+ *
1006
+ * @param query The query.
1007
+ * @param disjunctiveFacets List of disjunctive facets.
1008
+ * @param refinements The current refinements, mapping facet names to a list of values.
1009
+ * @return A list of queries suitable for {@link Index#multipleQueries}.
1010
+ */
1011
+ private @ NonNull List <Query > computeDisjunctiveFacetingQueries (@ NonNull Query query , @ NonNull List <String > disjunctiveFacets , @ NonNull Map <String , List <String >> refinements ) {
1012
+ // Retain only refinements corresponding to the disjunctive facets.
1013
+ Map <String , List <String >> disjunctiveRefinements = computeDisjunctiveRefinements (disjunctiveFacets , refinements );
975
1014
976
1015
// build queries
977
1016
// TODO: Refactor using JSON array notation: safer and clearer.
978
- List <IndexQuery > queries = new ArrayList <>();
1017
+ List <Query > queries = new ArrayList <>();
979
1018
// hits + regular facets query
980
1019
StringBuilder filters = new StringBuilder ();
981
1020
boolean first_global = true ;
@@ -1010,7 +1049,7 @@ protected JSONObject searchDisjunctiveFaceting(@NonNull Query query, @NonNull Li
1010
1049
}
1011
1050
}
1012
1051
1013
- queries .add (new IndexQuery ( this . indexName , new Query (query ).set ("facetFilters" , filters .toString () )));
1052
+ queries .add (new Query (query ).set ("facetFilters" , filters .toString ()));
1014
1053
// one query per disjunctive facet (use all refinements but the current one + hitsPerPage=1 + single facet
1015
1054
for (String disjunctiveFacet : disjunctiveFacets ) {
1016
1055
filters = new StringBuilder ();
@@ -1049,11 +1088,25 @@ protected JSONObject searchDisjunctiveFaceting(@NonNull Query query, @NonNull Li
1049
1088
}
1050
1089
}
1051
1090
String [] facets = new String []{disjunctiveFacet };
1052
- queries .add (new IndexQuery ( this . indexName , new Query (query ).setHitsPerPage (0 ).setAnalytics (false )
1091
+ queries .add (new Query (query ).setHitsPerPage (0 ).setAnalytics (false )
1053
1092
.setAttributesToRetrieve ().setAttributesToHighlight ().setAttributesToSnippet ()
1054
- .setFacets (facets ).set ("facetFilters" , filters .toString ()))) ;
1093
+ .setFacets (facets ).set ("facetFilters" , filters .toString ()));
1055
1094
}
1056
- JSONObject answers = this .client .multipleQueries (queries , null );
1095
+ return queries ;
1096
+ }
1097
+
1098
+ /**
1099
+ * Aggregate results from multiple queries into disjunctive faceting results.
1100
+ *
1101
+ * @param answers The response from the multiple queries.
1102
+ * @param disjunctiveFacets List of disjunctive facets.
1103
+ * @param refinements Facet refinements.
1104
+ * @return The aggregated results.
1105
+ * @throws AlgoliaException
1106
+ */
1107
+ private JSONObject aggregateDisjunctiveFacetingResults (@ NonNull JSONObject answers , @ NonNull List <String > disjunctiveFacets , @ NonNull Map <String , List <String >> refinements ) throws AlgoliaException
1108
+ {
1109
+ Map <String , List <String >> disjunctiveRefinements = computeDisjunctiveRefinements (disjunctiveFacets , refinements );
1057
1110
1058
1111
// aggregate answers
1059
1112
// first answer stores the hits + regular facets
@@ -1099,4 +1152,21 @@ protected JSONObject browseFrom(@NonNull String cursor) throws AlgoliaException
1099
1152
throw new Error (e ); // Should never happen: UTF-8 is always supported.
1100
1153
}
1101
1154
}
1155
+
1156
+ /**
1157
+ * Run multiple queries on this index with one API call.
1158
+ * A variant of {@link Client#multipleQueries(List, String)} where all queries target this index.
1159
+ *
1160
+ * @param queries Queries to run.
1161
+ * @param strategy Strategy to use.
1162
+ * @return The JSON results returned by the server.
1163
+ * @throws AlgoliaException
1164
+ */
1165
+ protected JSONObject multipleQueries (@ NonNull List <Query > queries , String strategy ) throws AlgoliaException {
1166
+ List <IndexQuery > requests = new ArrayList <>(queries .size ());
1167
+ for (Query query : queries ) {
1168
+ requests .add (new IndexQuery (this , query ));
1169
+ }
1170
+ return client .multipleQueries (requests , strategy );
1171
+ }
1102
1172
}
0 commit comments