android_small_white Created with Sketch.

Advanced

Custom batch - batchAsync

You may want to perform multiple operations with one API call to reduce latency.

If you have one index per user, you may want to perform a batch operations across several indices. We expose a method to perform this type of batch:

List<JSONObject> array = new ArrayList<>();
array.add(new JSONObject()
  .put("action", "addObject")
  .put("indexName", "index1")
  .put("body", new JSONObject()
      .put("firstname", "Jimmie")
      .put("lastname", "Barninger")
  )
);
array.add(new JSONObject()
  .put("action", "addObject")
  .put("indexName", "index2")
  .put("body", new JSONObject()
      .put("firstname", "Warren")
      .put("lastname", "Speach")
  )
);
client.batchAsync(new JSONArray(array), null);

The attribute action can have these values:

  • addObject
  • updateObject
  • partialUpdateObject
  • partialUpdateObjectNoCreate
  • deleteObject

Backup / Export an index - browseAsync

The search method cannot return more than 1,000 results. If you need to retrieve all the content of your index (for backup, SEO purposes or for running a script on it), you should use the browse method instead. This method lets you retrieve objects beyond the 1,000 limit.

This method is optimized for speed. To make it fast, distinct, typo-tolerance, word proximity, geo distance and number of matched words are disabled. Results are still returned ranked by attributes and custom ranking.

Response Format

Sample
{
  "hits": [
    {
      "firstname": "Jimmie",
      "lastname": "Barninger",
      "objectID": "433"
    }
  ],
  "processingTimeMS": 7,
  "query": "",
  "params": "filters=level%3D20",
  "cursor": "ARJmaWx0ZXJzPWxldmVsJTNEMjABARoGODA4OTIzvwgAgICAgICAgICAAQ=="
}
Fields
  • cursor (string, optional): A cursor to retrieve the next chunk of data. If absent, it means that the end of the index has been reached.
  • query (string): Query text used to filter the results.
  • params (string, URL-encoded): Search parameters used to filter the results.
  • processingTimeMS (integer): Time that the server took to process the request, in milliseconds. Note: This does not include network time.

The following fields are provided for convenience purposes, and only when the browse is not filtered:

  • nbHits (integer): Number of objects in the index.
  • page (integer): Index of the current page (zero-based).
  • hitsPerPage (integer): Maximum number of hits returned per page.
  • nbPages (integer): Number of pages corresponding to the number of hits. Basically, ceil(nbHits / hitsPerPage).

Example

Using the low-level methods:

index.browseAsync(query, new CompletionHandler() {
    @Override
    public void requestCompleted(JSONObject result, AlgoliaException error) {
        if (error != null) return;
        // Handle the content. [...]
        // If there is more content, continue browse.
        String cursor = result.optString("cursor", null);
        if (cursor != null) {
            index.browseFrom(cursor, new CompletionHandler() {
                @Override
                public void requestCompleted(JSONObject result, AlgoliaException error) {
                    // Handle more content. [...]
                }
            });
        }
    }
});

Using the browse helper:

BrowseIterator iterator = new BrowseIterator(index, query, new BrowseIterator.BrowseIteratorHandler() {
    @Override
    public void handleBatch(@NonNull BrowseIterator iterator, JSONObject result, AlgoliaException error) {
        // Handle the result/error. [...]
        // You may optionally cancel the iteration by calling:
        iterator.cancel();
    }
});
iterator.start();

Retry logic

Algolia’s architecture is heavily redundant, to provide optimal reliability. Every application is hosted on at least three different servers. As a developer, however, you don’t need to worry about those details. The API Client handles them for you:

  • It leverages our dynamic DNS to perform automatic load balancing between servers.
  • Its retry logic switches the targeted server whenever it detects that one of them is down or unreachable. Therefore, a given request will not fail unless all servers are down or unreachable at the same time.

Application-level errors (e.g. invalid query) are still reported without retry.

Error handling

Requests can fail for two main reasons:

  1. Network issues: the server could not be reached, or did not answer within the timeout.
  2. Application error: the server rejected the request.

In the latter case, the error reported by the API client contains:

  • an HTTP status code indicating the type of error;
  • an error message indicating the cause of the error.

The error message is purely informational and intended for the developer. You should never rely on its content programmatically, as it may change without notice.

Configuring timeouts

Network & DNS resolution can be slow. That is why we have pre-configured timeouts. We do not advise to change them, but it could make sense to change them in some special cases:

  APIClient client = new ApiClient(...);
  client.setConnectTimeout(2000); // connection timeout
  client.setReadTimeout(30000); // read timeout
  client.setSearchTimeout(5000) // read timeout for search requests
  client.setHostDownDelay(5000); // delay before retrying a host we know was down