TestsTested | ✓ |
LangLanguage | Obj-CObjective C |
License | MIT |
ReleasedLast Release | Apr 2016 |
Maintained by Julien lemoine, Xavier Grand, redox, Thibault Deutsch, Clément Le Provost.
<Welcome Swift developers>
In June 2015, we release our Swift API Client.
It is able to work with Swift and Objective-C. If you plan to use Swift in your project, please use it since we don't support Swift in our Objective-C API Client.
The Objective-C API Client is still supported and updated.
</Welcome Swift developers>
Algolia Search is a hosted full-text, numerical, and faceted search engine capable of delivering realtime results from the first keystroke.
Our Objective-C client lets you easily use the Algolia Search API from your iOS & OS X applications. It wraps the Algolia Search REST API.
Getting Started
Commands Reference
To setup your project, follow these steps:
pod 'AlgoliaSearch-Client', '~> 3.5'
in your Podfile (or pod 'AlgoliaSearch-Client', '~> 2.0'
if your are using AFNetworking 1.x in your project) or drop the source folder on your project (If you are not using a Podfile, you will also need to add AFNetworking library in your project).#import "ASAPIClient.h"
call to your projectASAPIClient *apiClient =
[ASAPIClient apiClientWithApplicationID:@"YourApplicationID" apiKey:@"YourAPIKey"];
In 30 seconds, this quick start tutorial will show you how to index and search objects.
Without any prior configuration, you can start indexing 500 contacts in the contacts
index using the following code:
// Load JSON file
NSString *jsonPath = [[NSBundle mainBundle] pathForResource:@"contacts" ofType:@"json"];
NSData* jsonData = [NSData dataWithContentsOfFile:jsonPath];
NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
// Load all objects of json file in an index named "contacts"
ASRemoteIndex *index = [apiClient getIndex:@"contacts"];
[index addObjects:dict[@"objects"] success:nil failure:nil];
You can now search for contacts using firstname, lastname, company, etc. (even with typos):
// search by firstname
[index search:[ASQuery queryWithFullTextQuery:@"jimmie"]
success:^(ASRemoteIndex *index, ASQuery *query, NSDictionary *result) {
NSLog(@"Result: %@", result);
} failure:nil];
// search a firstname with typo
[index search:[ASQuery queryWithFullTextQuery:@"jimie"]
success:^(ASRemoteIndex *index, ASQuery *query, NSDictionary *result) {
NSLog(@"Result: %@", result);
} failure:nil];
// search for a company
[index search:[ASQuery queryWithFullTextQuery:@"california paint"]
success:^(ASRemoteIndex *index, ASQuery *query, NSDictionary *result) {
NSLog(@"Result: %@", result);
} failure:nil];
// search for a firstname & company
[index search:[ASQuery queryWithFullTextQuery:@"jimmie paint"]
success:^(ASRemoteIndex *index, ASQuery *query, NSDictionary *result) {
NSLog(@"Result: %@", result);
} failure:nil];
Settings can be customized to tune the search behavior. For example, you can add a custom sort by number of followers to the already great built-in relevance:
NSArray *customRanking = @[@"desc(followers)"];
NSDictionary *settings = @{@"customRanking": customRanking};
[index setSettings:settings success:nil
failure:^(ASRemoteIndex *index, NSDictionary *settings, NSString *errorMessage) {
NSLog(@"Error when applying settings: %@", errorMessage);
}];
You can also configure the list of attributes you want to index by order of importance (first = most important):
NSArray *customRanking = @[@"lastname", @"firstname", @"company", @"email", @"city", @"address"];
NSDictionary *settings = @{@"attributesToIndex": customRanking};
[index setSettings:settings success:nil
failure:^(ASRemoteIndex *index, NSDictionary *settings, NSString *errorMessage) {
NSLog(@"Error when applying settings: %@", errorMessage);
}];
Since the engine is designed to suggest results as you type, you'll generally search by prefix. In this case the order of attributes is very important to decide which hit is the best:
[index search:[ASQuery queryWithFullTextQuery:@"or"]
success:^(ASRemoteIndex *index, ASQuery *query, NSDictionary *result) {
NSLog(@"Result: %@", result);
} failure:nil];
[index search:[ASQuery queryWithFullTextQuery:@"jim"]
success:^(ASRemoteIndex *index, ASQuery *query, NSDictionary *result) {
NSLog(@"Result: %@", result);
} failure:nil];
Check our online guides:
Each entry in an index has a unique identifier called objectID
. There are two ways to add en entry to the index:
objectID
assignment. You will be able to access it in the answer.objectID
.You don't need to explicitly create an index, it will be automatically created the first time you add an object. 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.
Example with automatic objectID
assignment:
NSDictionary *newObject = @{@"firstname": @"Jimmie", @"lastname": @"Barninger"};
[index addObject:newObject
success:^(ASRemoteIndex *index, NSDictionary *object, NSDictionary *result) {
NSLog(@"Object ID: %@", result[@"objectID"]);
} failure:nil];
Example with manual objectID
assignment:
NSDictionary *newObject = @{@"firstname": @"Jimmie", @"lastname": @"Barninger"};
[index addObject:newObject withObjectID:@"myID"
success:^(ASRemoteIndex *index, NSDictionary *object, NSString *objectID, NSDictionary *result) {
NSLog(@"Object ID: %@", result[@"objectID"]);
} failure:nil];
You have three options when updating an existing object:
Example on how to replace all attributes of an existing object:
NSDictionary *newObject = @{
@"firstname": @"Jimmie",
@"lastname": @"Barninger",
@"city": @"New York"
};
[index saveObject:newObject objectID:@"myID" success:nil failure:nil];
You have many ways to update an object's attributes:
Example to update only the city attribute of an existing object:
NSDictionary *partialObject = @{@"city": @"San Francisco"};
[index partialUpdateObject:partialObject objectID:@"myID" success:nil failure:nil];
Example to add a tag:
NSDictionary *operation = @{
@"value": @"MyTag",
@"_operation": @"Add"
};
NSDictionary *partialObject = @{@"_tags": operation};
[index partialUpdateObject:partialObject objectID:@"myID" success:nil failure:nil];
Example to remove a tag:
NSDictionary *operation = @{
@"value": @"MyTag",
@"_operation": @"Remove"
};
NSDictionary *partialObject = @{@"_tags": operation};
[index partialUpdateObject:partialObject objectID:@"myID" success:nil failure:nil];
Example to add a tag if it doesn't exist:
NSDictionary *operation = @{
@"value": @"MyTag",
@"_operation": @"AddUnique"
};
NSDictionary *partialObject = @{@"_tags": operation};
[index partialUpdateObject:partialObject objectID:@"myID" success:nil failure:nil];
Example to increment a numeric value:
NSDictionary *operation = @{
@"value": 42,
@"_operation": @"Increment"
};
NSDictionary *partialObject = @{@"price": operation};
[index partialUpdateObject:partialObject objectID:@"myID" success:nil failure:nil];
Note: Here we are incrementing the value by 42
. To increment just by one, put
value:1
.
Example to decrement a numeric value:
NSDictionary *operation = @{
@"value": 42,
@"_operation": @"Decrement"
};
NSDictionary *partialObject = @{@"price": operation};
[index partialUpdateObject:partialObject objectID:@"myID" success:nil failure:nil];
Note: Here we are decrementing the value by 42
. To decrement just by one, put
value:1
.
To perform a search, you only need to initialize the index and perform a call to the search function.
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
ASRemoteIndex *index = [apiClient getIndex:@"contacts"];
[index search:[ASQuery queryWithFullTextQuery:@"s"]
success:^(ASRemoteIndex *index, ASQuery *query, NSDictionary *result) {
NSLog(@"Result: %@", result);
} failure:nil];
ASQuery *query = [ASQuery queryWithFullTextQuery:@"s"];
query.attributesToRetrieve = @[@"firstname", @"lastname"];
query.hitsPerPage = 50;
[index search:query
success:^(ASRemoteIndex *index, ASQuery *query, NSDictionary *result) {
NSLog(@"Result: %@", result);
} failure:nil];
The server response will look like:
{
"hits": [
{
"firstname": "Jimmie",
"lastname": "Barninger",
"objectID": "433",
"_highlightResult": {
"firstname": {
"value": "<em>Jimmie</em>",
"matchLevel": "partial"
},
"lastname": {
"value": "Barninger",
"matchLevel": "none"
},
"company": {
"value": "California <em>Paint</em> & Wlpaper Str",
"matchLevel": "partial"
}
}
}
],
"page": 0,
"nbHits": 1,
"nbPages": 1,
"hitsPerPage": 20,
"processingTimeMS": 1,
"query": "jimmie paint",
"params": "query=jimmie+paint&attributesToRetrieve=firstname,lastname&hitsPerPage=50"
}
You can use the following optional arguments on ASQuery class:
fullTextQuery Type: string |
The instant search query string, used to set the string you want to search in your index. If no query parameter is set, the textual search will match with all the objects. |
setQueryType Default: prefixLast |
Selects how the query words are interpreted. It can be one of the following values:
|
setRemoveWordsIfNoResults Default: none |
This option is used to select a strategy in order to avoid having an empty result page. There are three different options:
|
minWordSizeForApprox1 Type: number
Default: 4
|
The minimum number of characters in a query word to accept one typo in this word. |
minWordSizeForApprox2 Type: number
Default: 8
|
The minimum number of characters in a query word to accept two typos in this word. |
setTypoTolerance Default: true |
This option allows you to control the number of typos allowed in the result set:
|
allowTyposOnNumericTokens Default: true |
If set to false, disables typo tolerance on numeric tokens (numbers). Defaults to true. |
ignorePlural Default: false |
If set to true, plural won't be considered as a typo. For example, car and cars, or foot and feet will be considered as equivalent. Defaults to false. |
disableTypoToleranceOnAttributes Default: [] |
List of attributes on which you want to disable typo tolerance (must be a subset of the |
restrictSearchableAttributes Default: attributesToIndex |
List of attributes you want to use for textual search (must be a subset of the |
removeStopWords Default: false |
Remove the stop words from query before executing it. Defaults to false. Contains a list of stop words from 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). In most use-cases, we don't recommend enabling this option. |
advancedSyntax Default: 0 (false) |
Enables the advanced query syntax. Defaults to 0 (false).
|
analytics Default: true |
If set to false, this query will not be taken into account in the analytics feature. Defaults to true. |
synonyms Default: true |
If set to false, this query will not use synonyms defined in the configuration. Defaults to true. |
replaceSynonymsInHighlight Default: true |
If set to false, words matched via synonym expansion will not be replaced by the matched synonym in the highlight results. Defaults to true. |
optionalWords Default: [] |
An array of strings that contain the list of words that should be considered as optional when found in the query. |
page Type: integer
Default: 0
|
Pagination parameter used to select the page to retrieve. |
hitsPerPage Type: integer
Default: 20
|
Pagination parameter used to select the number of hits per page. Defaults to 20. |
searchAroundLatitude:longitude: Type: float,float |
Search for entries around a given latitude/longitude. |
searchAroundLatitude:longitude:maxDist:precision |
Search for entries around a given latitude/longitude with a given precision for ranking. 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. |
searchAroundLatitudeLongitudeViaIP |
Search for entries around the latitude/longitude automatically computed from user IP address. |
searchAroundLatitudeLlongitude:precision |
Search for entries around a latitude/longitude automatically computed from user IP address with a given precision for ranking. For example if you set precision=100, two objects that are a distance of less than 100 meters will be considered as identical for the "geo" ranking parameter. |
searchInsideBoundingBoxWithLatitudeP1:longitudeP1:latitudeP2:longitudeP2 |
Search entries inside a given area defined by the two extreme points of a rectangle (defined by 4 floats: p1Lat,p1Lng,p2Lat,p2Lng). |
searchInsidePolygon: |
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). |
attributesToRetrieve |
The list of attributes you want to retrieve in order to minimize the size of the JSON answer. By default, all attributes are retrieved. You can also use |
attributesToHighlight |
The list of attributes you want to highlight according to the query. If an attribute has no match for the query, the raw value is returned. By default, all indexed attributes are highlighted. You can use
|
attributesToSnippet |
The list of attributes to snippet alongside the number of words to return (syntax is |
getRankingInfo |
If set to YES, the result hits will contain ranking information in the _rankingInfo attribute. |
setHighlightingTags Type: string, string |
Specify the string that is inserted before the highlighted parts in the query result (defaults to "<em>") and the string that is inserted after the highlighted parts in the query result (defaults to "</em>").. |
setSnippetEllipsisText |
String used as an ellipsis indicator when a snippet is truncated (defaults to empty). |
numericFilters |
A string that contains the comma separated list of numeric filters you want to apply. The filter syntax is |
You can easily perform range queries via the :
operator. This is equivalent to combining a >=
and <=
operand. For example, numericFilters=price:10 to 1000
.
You can also mix OR and AND operators. The OR operator is defined with a parenthesis syntax. For example, (code=1 AND (price:[0-100] OR price:[1000-2000]))
translates to encodeURIComponent("code=1,(price:0 to 100,price:1000 to 2000)")
.
You can also use a string array encoding (for example numericFilters: ["price>100","price<1000"]
).
tagFilters |
Filter the query by a set of tags. You can AND tags by separating them with commas. To OR tags, you must add parentheses. For example, At indexing, tags should be added in the _tags attribute of objects. For example |
facetFilters |
Filter the query with a list of facets. Facets are separated by commas and is encoded as |
facets |
List of object attributes that you want to use for faceting. For each of the declared attributes, you'll be able to retrieve a list of the most relevant facet values, and their associated count for the current query. Attributes are separated by a comma. For example, |
maxValuesPerFacet |
Limit the number of facet values returned for each facet. For example, |
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:
The list of keywords is:
|
Note: To specify a value with spaces or with a value equal to a keyword, it's possible to add quotes.
Warning:
distinct |
If set to YES, enables the distinct feature, disabled by default, if the |
To get a full understanding of how Distinct
works, you can have a look at our guide on distinct.
You can easily cache the results of the search queries by enabling the search cache. The results will be cached during a defined amount of time (default: 2 min). There is no pre-caching mechanism but you can simulate it by making a preemptive search query.
By default, the cache is disabled.
[myIndex enableSearchCache];
Or:
[myIndex enableSearchCacheWithExpiringTimeInterval:300];
You can send multiple queries with a single API call using a batch of queries:
// perform 3 queries in a single API call:
// - 1st query targets index `categories`
// - 2nd and 3rd queries target index `products`
NSArray *queries = @[
@{@"indexName": @"categories", @"query": anASQueryObject},
@{@"indexName": @"products", @"query": anotherASQueryObject},
@{@"indexName": @"products", @"query": anotherASQueryObject}
];
[client multipleQueries:queries
success:^(ASAPIClient *client, NSArray *queries, NSDictionary *result) {
NSLog(@"Result: %@", result);
} failure:nil];
The resulting JSON answer contains a results
array storing the underlying queries answers. The answers order is the same than the requests order.
You can specify a strategy
parameter to optimize your multiple queries:
none
: Execute the sequence of queries until the end.stopIfEnoughMatches
: Execute the sequence of queries until the number of hits is reached by the sum of hits.You can easily retrieve an object using its objectID
and optionally specify a comma separated list of attributes you want:
// Retrieves all attributes
[index getObject:@"myID"
success:^(ASRemoteIndex *index, NSString *objectID, NSDictionary *result) {
NSLog(@"Object: %@", result);
} failure:nil];
// Retrieves only the firstname attribute
[index getObject:@"myID" attributesToRetrieve:@[@"firstname"]
success:^(ASRemoteIndex *index, NSString *objectID, NSArray *attributesToRetrieve, NSDictionary *result) {
NSLog(@"Object: %@", result);
} failure:nil];
You can also retrieve a set of objects:
[index getObjects:@[@"myID1", @"myID2"]
success:^(ASRemoteIndex *index, NSArray *objectIDs, NSDictionary *result) {
// do something
} failure:nil];
You can delete an object using its objectID
:
[index deleteObject:@"myID" success:nil failure:nil];
You can delete all objects matching a single query with the following code. Internally, the API client performs the query, deletes all matching hits, and waits until the deletions have been applied.
ASQuery *query = /* [...] */;
[index deleteByQuery:query success:nil failure:nil];
You can easily retrieve or update settings:
[index getSettings:^(ASRemoteIndex *index, NSDictionary *result) {
NSLog(@"Settings: %@", result);
} failure:nil];
NSArray *customRanking = @[@"desc(followers)", @"asc(name)"];
NSDictionary *settings = @{@"customRanking": customRanking};
[index setSettings:settings success:nil failure:nil];
attributesToIndex Type: array of strings |
The list of attributes you want index (i.e. to make searchable). If set to null, all textual and numerical attributes of your objects are indexed. Make sure you updated this setting to get optimal results. This parameter has two important uses:
|
attributesForFaceting Type: 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. |
attributeForDistinct Type: string |
The name of the attribute used for the |
ranking Type: array of strings |
Controls the way results are sorted. We have nine available criteria:
|
customRanking Type: array of strings |
Lets you specify part of the ranking. The syntax of this condition is an array of strings containing attributes prefixed by the asc (ascending order) or desc (descending order) operator. For example, To get a full description of how the Custom Ranking works, you can have a look at our Ranking guide. |
queryType Default: prefixLast |
Select how the query words are interpreted. It can be one of the following values:
|
separatorsToIndex Default: empty |
Specify the separators (punctuation characters) to index. By default, separators are not indexed. Use |
slaves |
The list of indices on which you want to replicate all write operations. In order to get response times in milliseconds, we pre-compute part of the ranking during indexing. If you want to use different ranking configurations depending of the use case, you need to create one index per ranking configuration. This option enables you to perform write operations only on this index and automatically update slave indices with the same operations. |
unretrievableAttributes Default: empty |
The list of attributes that cannot be retrieved at query time. This feature allows you to have attributes that are used for indexing and/or ranking but cannot be retrieved. Defaults to null. Warning: for testing purposes, this setting is ignored when you're using the ADMIN API Key. |
allowCompressionOfIntegerArray Default: false |
Allows compression of big integer arrays. In data-intensive use-cases, we recommended enabling this feature and then storing the list of user IDs or rights as an integer array. When enabled, the integer array is reordered to reach a better compression ratio. Defaults to false. |
synonyms Type: array of array of string considered as equals |
For example, you may want to retrieve the black ipad record when your users are searching for dark ipad, even if the word dark is not part of the record. To do this, you need to configure black as a synonym of dark. For example, |
placeholders Type: 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,
|
disableTypoToleranceOnWords Type: string array |
Specify a list of words on which automatic typo tolerance will be disabled. |
disableTypoToleranceOnAttributes Type: string array |
List of attributes on which you want to disable typo tolerance (must be a subset of the |
altCorrections Type: object array |
Specify alternative corrections that you want to consider. Each alternative correction is described by an object containing three attributes:
For example |
minWordSizefor1Typo Type: integer
Default: 4
|
The minimum number of characters needed to accept one typo (default = 4). |
minWordSizefor2Typos Type: integer
Default: 8
|
The minimum number of characters needed to accept two typos (default = 8). |
hitsPerPage Type: integer
Default: 10
|
The number of hits per page (default = 10). |
attributesToRetrieve Type: array of strings |
Default list of attributes to retrieve in objects. If set to null, all attributes are retrieved. |
attributesToHighlight Type: array of strings |
Default list of attributes to highlight. If set to null, all indexed attributes are highlighted. |
attributesToSnippet Type: array of strings |
Default list of attributes to snippet alongside the number of words to return (syntax is |
highlightPreTag Type: string |
Specify the string that is inserted before the highlighted parts in the query result (defaults to |
highlightPostTag Type: string |
Specify the string that is inserted after the highlighted parts in the query result (defaults to |
optionalWords Type: array of strings |
Specify a list of words that should be considered optional when found in the query. |
allowTyposOnNumericTokens Type: boolean
Default: false
|
If set to false, disable typo-tolerance on numeric tokens (=numbers) in the query word. For example the query |
ignorePlurals Type: boolean
Default: false
|
If set to true, singular/plural forms won’t be considered as typos (for example car/cars and foot/feet will be considered as equivalent). Defaults to false. |
advancedSyntax Type: integer (0 or 1)
Default: 0
|
Enable the advanced query syntax. Defaults to 0 (false).
|
replaceSynonymsInHighlight Type: boolean
Default: true
|
If set to false, words matched via synonyms expansion will not be replaced by the matched synonym in the highlighted result. Defaults to true. |
maxValuesPerFacet Type: integer |
Limit the number of facet values returned for each facet. For example: |
distinct Type: integer (0 or 1)
Default: 0
|
Enable the distinct feature (disabled by default) if the To get a full understanding of how |
typoTolerance Type: string
Default: true
|
This setting has four different options:
|
removeStopWords Type: boolean
Default: false
|
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) |
You can list all your indices along with their associated information (number of entries, disk size, etc.) with the listIndexes
method:
[client listIndexes:^(ASAPIClient *client, NSDictionary *result) {
NSLog(@"Indexes: %@", result);
} failure:nil];
You can delete an index using its name:
[client deleteIndex:@"contacts" success:nil
failure:^(ASAPIClient *client, NSString *indexName, NSString *errorMessage) {
NSLog(@"Could not delete: %@", errorMessage);
}];
You can delete the index contents without removing settings and index specific API keys by using the clearIndex command:
[index clearIndex:nil
failure:^(ASRemoteIndex *index, NSString *errorMessage) {
NSLog(@"Could not clear index: %@", errorMessage);
}];
All write operations in Algolia are asynchronous by design.
It means that when you add or update an object to your index, our servers will
reply to your request with a taskID
as soon as they understood the write
operation.
The actual insert and indexing will be done after replying to your code.
You can wait for a task to complete using the waitTask
method on the taskID
returned by a write operation.
For example, to wait for indexing of a new object:
[index addObject:newObject
success:^(ASRemoteIndex *index, NSDictionary *object, NSDictionary *result) {
// Wait task
[index waitTask:result[@"taskID"]
success:^(ASRemoteIndex *index, NSString *taskID, NSDictionary *result) {
NSLog(@"New object is indexed");
} failure:nil];
} failure:nil];
If you want to ensure multiple objects have been indexed, you only need to check
the biggest taskID
.
You may want to perform multiple operations with one API call to reduce latency. We expose four methods to perform batch operations:
addObjects
: Add an array of objects using automatic objectID
assignment.saveObjects
: Add or update an array of objects that contains an objectID
attribute.deleteObjects
: Delete an array of objectIDs.partialUpdateObjects
: Partially update an array of objects that contain an objectID
attribute (only specified attributes will be updated).Example using automatic objectID
assignment:
NSDictionary *obj1 = @{@"firstname": @"Jimmie", @"lastname": @"Barninger"};
NSDictionary *obj2 = @{@"firstname": @"Warren", @"lastname": @"Speach"};
[index addObjects:@[obj1, obj2]
success:^(ASRemoteIndex *index, NSArray *objects, NSDictionary *result) {
NSLog(@"Object IDs: %@", result);
} failure:nil];
Example with user defined objectID
(add or update):
NSDictionary *obj1 = @{@"firstname": @"Jimmie", @"lastname": @"Barninger", @"objectID": @"myID1"};
NSDictionary *obj2 = @{@"firstname": @"Warren", @"lastname": @"Speach", @"objectID": @"myID2"};
[index saveObjects:@[obj1, obj2]
success:^(ASRemoteIndex *index, NSArray *objects, NSDictionary *result) {
NSLog(@"Object IDs: %@", result);
} failure:nil];
Example that deletes a set of records:
[index deleteObjects:@[@"myID1", @"myID2"] success:nil failure:nil];
Example that updates only the firstname
attribute:
NSDictionary *obj1 = @{@"firstname": @"Jimmie", @"objectID": @"myID1"};
NSDictionary *obj2 = @{@"firstname": @"Warren", @"objectID": @"myID2"};
[index partialUpdateObjects:@[obj1, obj2]
success:^(ASRemoteIndex *index, NSArray *objects, NSDictionary *result) {
NSLog(@"Object IDs: %@", result);
} failure:nil];
If you have one index per user, you may want to perform a batch operations across severals indexes. We expose a method to perform this type of batch:
NSArray *requests = @[
@{@"action": @"addObject", @"indexName": @"index1", @"body": @{@"firstname": @"Jimmie", @"lastname": @"Barninger"}},
@{@"action": @"addObject", @"indexName": @"index2", @"body": @{@"firstname": @"Warren", @"lastname": @"Speach"}}
];
[client batch:requests
success:^(ASRemoteIndex *index, NSArray *request, NSDictionary *result) {
NSLog(@"Object IDs: %@", result);
} failure:nil];
The attribute action can have these values:
The ADMIN API key provides full control of all your indices. You can also generate user API keys to control security. These API keys can be restricted to a set of operations or/and restricted to a given index.
To list existing keys, you can use listUserKeys
method:
// Lists global API Keys
[apiClient listUserKeys:^(ASAPIClient *client, NSDictionary *result) {
NSLog(@"User keys: %@", result);
} failure:nil];
// Lists API Keys that can access only to this index
[index listUserKeys:^(ASRemoteIndex *index, NSDictionary *result) {
NSLog(@"User keys: %@", result);
} failure:nil];
Each key is defined by a set of permissions that specify the authorized actions. The different permissions are:
Example of API Key creation:
// Creates a new global API key that can only perform search actions
[apiClient addUserKey:@[@"search"]
success:^(ASAPIClient *client, NSArray *acls, NSDictionary *result) {
NSLog(@"API Key: %@", result[@"key"]);
} failure:nil];
// Creates a new API key that can only perform search action on this index
[index addUserKey:@[@"search"]
success:^(ASRemoteIndex *index, NSArray *acls, NSDictionary *result) {
NSLog(@"API Key: %@", result[@"key"]);
} failure:nil];
You can also create an API Key with advanced settings:
validity |
Add a validity period. The key will be valid for a specific period of time (in seconds). |
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. |
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. |
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. |
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. |
queryParameters |
Specify the list of query parameters. You can force the query parameters for a query using the url string format (param1=X¶m2=Y...). |
description |
Specify a description to describe where the key is used. |
// Creates a new index specific API key valid for 300 seconds, with a rate limit of 100 calls per hour per IP and a maximum of 20 hits
NSDictionary *params = @{@"validity": 300, @"maxQueriesPerIPPerHour": 100
, @"maxHitsPerQuery": 20, @"indexes": @[@"dev_*"], @"referers": @[@"algolia.com/*"]
, @"queryParameters": @"typoTolerance=strict&ignorePlurals=false"
, @"description": @"Limited search only API key for algolia.com"};
[index addUserKey:[@"search"] withParams:params
success:^(ASRemoteIndex *index, NSArray *acls, NSDictionary* params, NSDictionary *result) {
NSLog(@"API Key: %@", result[@"key"]);
} failure:nil];
Update the permissions of an existing key:
// Update an existing global API key that is valid for 300 seconds
[apiClient updateUserKey:@"myAPIKey", withACL:@[@"search"] withValidity:300 maxQueriesPerIPPerHour:0 maxHitsPerQuery:0
success:^(ASAPIClient *client, NSString *key, NSArray *acls, NSDictionary *result) {
NSLog(@"API Key: %@", result[@"key"]);
} failure:nil];
// Update an existing index specific API key valid for 300 seconds, with a rate limit of 100 calls per hour per IP and a maximum of 20 hits
[index updateUserKey:@"myAPIKey" withACL:@[@"search"] withValidity:300 maxQueriesPerIPPerHour:100 maxHitsPerQuery:20
success:^(ASRemoteIndex *index, NSString *key, NSArray *acls, NSDictionary *result) {
NSLog(@"API Key: %@", result[@"key"]);
} failure:nil];
Get the permissions of a given key:
// Gets the rights of a global key
[apiClient getUserKeyACL:@"79710f2fbe18a06fdf12c17a16878654"
success:^(ASAPIClient *client, NSString *key, NSDictionary *result) {
NSLog(@"Key details: %@", result);
} failure:nil];
// Gets the rights of an index specific key
[index getUserKeyACL:@"013464b04012cb73299395a635a2fc6c"
success:^(ASRemoteIndex *index, NSString *key, NSDictionary *result) {
NSLog(@"Key details: %@", result);
} failure:nil];
Delete an existing key:
// Deletes a global key
[apiClient deleteUserKey:@"79710f2fbe18a06fdf12c17a16878654" success:nil
failure:^(ASAPIClient *client, NSString *key, NSString *errorMessage) {
NSLog(@"Delete error: %@", errorMessage);
}];
// Deletes an index specific key
[index deleteUserKey:@"013464b04012cb73299395a635a2fc6c" success:nil
failure:^(ASRemoteIndex *index, NSString *key, NSString *errorMessage) {
NSLog(@"Delete error: %@", errorMessage);
}];
You can easily copy or rename an existing index using the copy
and move
commands.
Note: Move and copy commands overwrite the destination index.
// Rename MyIndex in MyIndexNewName
[apiClient moveIndex:@"MyIndex" to:@"MyIndexNewName"
success:^(ASAPIClient *client, NSString *srcIndexName, NSString *dstIndexName, NSDictionary *result) {
NSLog(@"Move Success: %@", result);
} failure:^(ASAPIClient *client, NSString *srcIndexName, NSString *dstIndexName, NSString *errorMessage) {
NSLog(@"Move Failure: %@", errorMessage);
}];
// Copy MyIndex in MyIndexCopy
[apiClient copyIndex:@"MyIndex" to:@"MyIndexCopy"
success:^(ASAPIClient *client, NSString *srcIndexName, NSString *dstIndexName, NSDictionary *result) {
NSLog(@"Copy Success: %@", result);
} failure:^(ASAPIClient *client, NSString *srcIndexName, NSString *dstIndexName, NSString *errorMessage) {
NSLog(@"Copy Failure: %@", errorMessage);
}];
The move command is particularly useful if you want to update a big index atomically from one version to another. For example, if you recreate your index MyIndex
each night from a database by batch, you only need to:
MyNewIndex
.MyNewIndex
to MyIndex
using the move command. This will automatically override the old index and new queries will be served on the new one.// Rename MyNewIndex in MyIndex (and overwrite it)
[apiClient moveIndex:@"MyNewIndex" to:@"MyIndex"
success:^(ASAPIClient *client, NSString *srcIndexName, NSString *dstIndexName, NSDictionary *result) {
NSLog(@"Move Success: %@", result);
} failure:^(ASAPIClient *client, NSString *srcIndexName, NSString *dstIndexName, NSString *errorMessage) {
NSLog(@"Move Failure: %@", errorMessage);
}];
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.
It will return a cursor
alongside your data, that you can then use to retrieve
the next chunk of your records.
You can specify custom parameters (like page
or hitsPerPage
) on your first
browse
call, and these parameters will then be included in the cursor
. Note
that it is not possible to access records beyond the 1,000th on the first call.
Example:
// Iterate with a filter over the index
[index browseWithQuery:query block:^(ASBrowseIterator *iterator, BOOL end, NSString *error) {
// Retrieve the next cursor from the browse method
NSLog(iterator.cursor);
if (error != nil) {
// Handle errors
} else if (end) {
// End of the index
} else {
// Do something
[iterator next];
}
}];
You can retrieve the latest logs via this API. Each log entry contains:
You can retrieve the logs of your last 1,000 API calls and browse them using the offset/length parameters:
offset |
Specify the first entry to retrieve (0-based, 0 is the most recent log entry). Defaults to 0. |
length |
Specify the maximum number of entries to retrieve starting at the offset. Defaults to 10. Maximum allowed value: 1,000. |
onlyErrors |
Retrieve only logs with an HTTP code different than 200 or 201. (deprecated) |
type |
Specify the type of logs to retrieve:
|
// Get last 10 log entries
[apiClient getLogs:^(ASAPIClient *client, NSDictionary *result) {
NSLog(@"GetLogs success: %@", result);
} failure:^(ASAPIClient *client, NSString *errorMessage) {
NSLog(@"GetLogs failure: %@", errorMessage);
}];
// Get last 100 log entries
[apiClient getLogsWithOffset:0 length:100
success:^(ASAPIClient *client, NSUInteger offset, NSUInteger length, NSDictionary *result) {
NSLog(@"GetLog success: %@", result);
} failure:^(ASAPIClient *client, NSUInteger offset, NSUInteger length, NSString *errorMessage) {
NSLog(@"GetLogs failure: %@", errorMessage);
}];