Skip to content
This repository was archived by the owner on Jan 31, 2022. It is now read-only.

Commit 4e1f208

Browse files
author
Clément Le Provost
committed
Merge branch 'feat/offline-only-index-with-transactions'
2 parents 0cdfe3c + f1608a7 commit 4e1f208

File tree

19 files changed

+2964
-215
lines changed

19 files changed

+2964
-215
lines changed

algoliasearch/build-offline.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ android {
4040
}
4141

4242
dependencies {
43-
offlineCompile "com.algolia:algoliasearch-offline-core-android:1.0"
43+
offlineCompile "com.algolia:algoliasearch-offline-core-android:1.0.1"
4444
}
4545

4646

algoliasearch/common.gradle

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ dependencies {
7878

7979
testCompile "junit:junit:4.12"
8080
testCompile "org.assertj:assertj-core:1.7.0"
81-
testCompile "org.robolectric:robolectric:3.0"
81+
testCompile "org.robolectric:robolectric:3.1.2"
8282

8383
// PowerMock brings in the mockito dependency
8484
testCompile "org.powermock:powermock-module-junit4:1.6.1"
@@ -100,6 +100,7 @@ task javadoc(type: Javadoc) {
100100
destinationDir = new File(projectDir, DOC_DIR)
101101
title = DOC_TITLE
102102
options.memberLevel = JavadocMemberLevel.PUBLIC
103+
options.noQualifiers = ["java.io", "java.lang", "java.util", "org.json"] // avoid fully qualifying usual classes
103104
options.noTimestamp = true // avoid noisy diffs
104105
options.overview = DOC_OVERVIEW
105106
classpath += project.files(android.getBootClasspath().join(File.pathSeparator))

algoliasearch/src/main/java/com/algolia/search/saas/Client.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ public int hashCode() {
128128
/** Thread pool used to run asynchronous requests. */
129129
protected ExecutorService searchExecutorService = Executors.newFixedThreadPool(4);
130130

131-
protected Map<String, WeakReference<Index>> indices = new HashMap<>();
131+
protected Map<String, WeakReference<Object>> indices = new HashMap<>();
132132

133133
// ----------------------------------------------------------------------
134134
// Initialization
@@ -330,13 +330,13 @@ public Index initIndex(@NonNull String indexName) {
330330
*/
331331
public @NonNull Index getIndex(@NonNull String indexName) {
332332
Index index = null;
333-
WeakReference<Index> existingIndex = indices.get(indexName);
333+
WeakReference<Object> existingIndex = indices.get(indexName);
334334
if (existingIndex != null) {
335-
index = existingIndex.get();
335+
index = (Index)existingIndex.get();
336336
}
337337
if (index == null) {
338338
index = new Index(this, indexName);
339-
indices.put(indexName, new WeakReference<Index>(index));
339+
indices.put(indexName, new WeakReference<Object>(index));
340340
}
341341
return index;
342342
}

algoliasearch/src/main/java/com/algolia/search/saas/Index.java

Lines changed: 8 additions & 153 deletions
Original file line numberDiff line numberDiff line change
@@ -26,22 +26,22 @@
2626
import android.support.annotation.NonNull;
2727
import android.support.annotation.Nullable;
2828

29+
import com.algolia.search.saas.helpers.DisjunctiveFaceting;
30+
2931
import org.json.JSONArray;
3032
import org.json.JSONException;
3133
import org.json.JSONObject;
3234

3335
import java.io.UnsupportedEncodingException;
3436
import java.net.URLEncoder;
3537
import java.util.ArrayList;
36-
import java.util.HashMap;
37-
import java.util.Iterator;
3838
import java.util.List;
3939
import java.util.Map;
4040

4141
/**
4242
* A proxy to an Algolia index.
4343
* <p>
44-
* You cannot construct this class directly. Please use {@link Client#initIndex(String)} to obtain an instance.
44+
* You cannot construct this class directly. Please use {@link Client#getIndex(String)} to obtain an instance.
4545
* </p>
4646
* <p>
4747
* WARNING: For performance reasons, arguments to asynchronous methods are not cloned. Therefore, you should not
@@ -173,21 +173,12 @@ protected byte[] searchSyncRaw(@NonNull Query query) throws AlgoliaException {
173173
* @return A cancellable request.
174174
*/
175175
public Request searchDisjunctiveFacetingAsync(@NonNull Query query, @NonNull final List<String> disjunctiveFacets, @NonNull final Map<String, List<String>> refinements, @NonNull final CompletionHandler completionHandler) {
176-
final List<Query> queries = computeDisjunctiveFacetingQueries(query, disjunctiveFacets, refinements);
177-
return multipleQueriesAsync(queries, null, new CompletionHandler() {
176+
return new DisjunctiveFaceting() {
178177
@Override
179-
public void requestCompleted(JSONObject content, AlgoliaException error) {
180-
JSONObject aggregatedResults = null;
181-
try {
182-
if (content != null) {
183-
aggregatedResults = aggregateDisjunctiveFacetingResults(content, disjunctiveFacets, refinements);
184-
}
185-
} catch (AlgoliaException e) {
186-
error = e;
187-
}
188-
completionHandler.requestCompleted(aggregatedResults, error);
178+
protected Request multipleQueriesAsync(@NonNull List<Query> queries, @NonNull CompletionHandler completionHandler) {
179+
return Index.this.multipleQueriesAsync(queries, null, completionHandler);
189180
}
190-
});
181+
}.searchDisjunctiveFacetingAsync(query, disjunctiveFacets, refinements, completionHandler);
191182
}
192183

193184
/**
@@ -1056,142 +1047,6 @@ protected JSONObject clearIndex() throws AlgoliaException {
10561047
return client.postRequest("/1/indexes/" + encodedIndexName + "/clear", "", false);
10571048
}
10581049

1059-
/**
1060-
* Filter disjunctive refinements from generic refinements and a list of disjunctive facets.
1061-
*
1062-
* @param disjunctiveFacets the array of disjunctive facets
1063-
* @param refinements Map representing the current refinements
1064-
* @return The disjunctive refinements
1065-
*/
1066-
private
1067-
@NonNull
1068-
Map<String, List<String>> computeDisjunctiveRefinements(@NonNull List<String> disjunctiveFacets, @NonNull Map<String, List<String>> refinements) {
1069-
Map<String, List<String>> disjunctiveRefinements = new HashMap<>();
1070-
for (Map.Entry<String, List<String>> elt : refinements.entrySet()) {
1071-
if (disjunctiveFacets.contains(elt.getKey())) {
1072-
disjunctiveRefinements.put(elt.getKey(), elt.getValue());
1073-
}
1074-
}
1075-
return disjunctiveRefinements;
1076-
}
1077-
1078-
/**
1079-
* Compute the queries to run to implement disjunctive faceting.
1080-
*
1081-
* @param query The query.
1082-
* @param disjunctiveFacets List of disjunctive facets.
1083-
* @param refinements The current refinements, mapping facet names to a list of values.
1084-
* @return A list of queries suitable for {@link Index#multipleQueries}.
1085-
*/
1086-
private @NonNull
1087-
List<Query> computeDisjunctiveFacetingQueries(@NonNull Query query, @NonNull List<String> disjunctiveFacets, @NonNull Map<String, List<String>> refinements) {
1088-
// Retain only refinements corresponding to the disjunctive facets.
1089-
Map<String, List<String>> disjunctiveRefinements = computeDisjunctiveRefinements(disjunctiveFacets, refinements);
1090-
1091-
// build queries
1092-
List<Query> queries = new ArrayList<>();
1093-
// hits + regular facets query
1094-
JSONArray filters = new JSONArray();
1095-
for (Map.Entry<String, List<String>> elt : refinements.entrySet()) {
1096-
JSONArray or = new JSONArray();
1097-
final boolean isDisjunctiveFacet = disjunctiveRefinements.containsKey(elt.getKey());
1098-
for (String val : elt.getValue()) {
1099-
if (isDisjunctiveFacet) {
1100-
// disjunctive refinements are ORed
1101-
or.put(String.format("%s:%s", elt.getKey(), val));
1102-
} else {
1103-
filters.put(String.format("%s:%s", elt.getKey(), val));
1104-
}
1105-
}
1106-
// Add or
1107-
if (isDisjunctiveFacet) {
1108-
filters.put(or);
1109-
}
1110-
}
1111-
1112-
queries.add(new Query(query).setFacetFilters(filters));
1113-
// one query per disjunctive facet (use all refinements but the current one + hitsPerPage=1 + single facet
1114-
for (String disjunctiveFacet : disjunctiveFacets) {
1115-
filters = new JSONArray();
1116-
1117-
for (Map.Entry<String, List<String>> elt : refinements.entrySet()) {
1118-
if (disjunctiveFacet.equals(elt.getKey())) {
1119-
continue;
1120-
}
1121-
JSONArray or = new JSONArray();
1122-
final boolean isDisjunctiveFacet = disjunctiveRefinements.containsKey(elt.getKey());
1123-
for (String val : elt.getValue()) {
1124-
if (isDisjunctiveFacet) {
1125-
// disjunctive refinements are ORed
1126-
or.put(String.format("%s:%s", elt.getKey(), val));
1127-
} else {
1128-
filters.put(String.format("%s:%s", elt.getKey(), val));
1129-
}
1130-
}
1131-
// Add or
1132-
if (isDisjunctiveFacet) {
1133-
filters.put(or);
1134-
}
1135-
}
1136-
String[] facets = new String[]{disjunctiveFacet};
1137-
queries.add(new Query(query).setHitsPerPage(0).setAnalytics(false)
1138-
.setAttributesToRetrieve().setAttributesToHighlight().setAttributesToSnippet()
1139-
.setFacets(facets).setFacetFilters(filters));
1140-
}
1141-
return queries;
1142-
}
1143-
1144-
/**
1145-
* Aggregate results from multiple queries into disjunctive faceting results.
1146-
*
1147-
* @param answers The response from the multiple queries.
1148-
* @param disjunctiveFacets List of disjunctive facets.
1149-
* @param refinements Facet refinements.
1150-
* @return The aggregated results.
1151-
* @throws AlgoliaException
1152-
*/
1153-
JSONObject aggregateDisjunctiveFacetingResults(@NonNull JSONObject answers, @NonNull List<String> disjunctiveFacets, @NonNull Map<String, List<String>> refinements) throws AlgoliaException {
1154-
Map<String, List<String>> disjunctiveRefinements = computeDisjunctiveRefinements(disjunctiveFacets, refinements);
1155-
1156-
// aggregate answers
1157-
// first answer stores the hits + regular facets
1158-
try {
1159-
boolean nonExhaustiveFacetsCount = false;
1160-
JSONArray results = answers.getJSONArray("results");
1161-
JSONObject aggregatedAnswer = results.getJSONObject(0);
1162-
JSONObject disjunctiveFacetsJSON = new JSONObject();
1163-
for (int i = 1; i < results.length(); ++i) {
1164-
if (!results.getJSONObject(i).optBoolean("exhaustiveFacetsCount")) {
1165-
nonExhaustiveFacetsCount = true;
1166-
}
1167-
JSONObject facets = results.getJSONObject(i).getJSONObject("facets");
1168-
@SuppressWarnings("unchecked")
1169-
Iterator<String> keys = facets.keys();
1170-
while (keys.hasNext()) {
1171-
String key = keys.next();
1172-
// Add the facet to the disjunctive facet hash
1173-
disjunctiveFacetsJSON.put(key, facets.getJSONObject(key));
1174-
// concatenate missing refinements
1175-
if (!disjunctiveRefinements.containsKey(key)) {
1176-
continue;
1177-
}
1178-
for (String refine : disjunctiveRefinements.get(key)) {
1179-
if (!disjunctiveFacetsJSON.getJSONObject(key).has(refine)) {
1180-
disjunctiveFacetsJSON.getJSONObject(key).put(refine, 0);
1181-
}
1182-
}
1183-
}
1184-
}
1185-
aggregatedAnswer.put("disjunctiveFacets", disjunctiveFacetsJSON);
1186-
if (nonExhaustiveFacetsCount) {
1187-
aggregatedAnswer.put("exhaustiveFacetsCount", false);
1188-
}
1189-
return aggregatedAnswer;
1190-
} catch (JSONException e) {
1191-
throw new AlgoliaException("Failed to aggregate results", e);
1192-
}
1193-
}
1194-
11951050
protected JSONObject browse(@NonNull Query query) throws AlgoliaException {
11961051
return client.getRequest("/1/indexes/" + encodedIndexName + "/browse?" + query.build(), true);
11971052
}
@@ -1220,4 +1075,4 @@ protected JSONObject multipleQueries(@NonNull List<Query> queries, String strate
12201075
}
12211076
return client.multipleQueries(requests, strategy);
12221077
}
1223-
}
1078+
}

0 commit comments

Comments
 (0)