Required API Key:
any key with the
addObject
ACL
About this method
Add new objects to an index or replace existing objects with an updated set of attributes.
The save method is used to redefine the entire set of an object’s attributes (except its objectID
). In other words, it fully replaces an existing object.
The saveObject
and saveObjects
methods replace addObject
and addObjects
respectively.
For more information, check the upgrade guide for your API client.
This method differs from partial update objects
in a significant way:
- With
saveObjects
, you define an object’s full set of attributes.
Attributes not specified will no longer exist.
For example, if an existing object contains the author
attribute, but you don’t define it in your update call, it removes the author
attribute from that object.
- In contrast, when using
partialUpdateObjects
, you can single out one or more attributes and either create or update their content.
If you don’t define an existing attribute in your update call, it doesn’t impact it.
To ensure good performance, saveObjects
automatically splits your records into batches of 1,000 objects. If you’re indexing many records and have a stable, high-speed internet connection, you can set the default batch size to a higher value to send more records per request and shorten your indexing time.
Automatic batching is only available in the latest major versions of Algolia’s JavaScript, PHP, Go, C#, Java, and Python clients.
When updating large numbers of objects, or large sizes, be aware of the rate limit. You’ll know you’ve reached the rate limit when you start receiving errors on your indexing operations. To resolve rate limiting errors, you need to wait before sending any further indexing operations.
Saving objects is a single transactional operation. If there’s an error saving one of your objects, **none of the objects you passed will be saved to your index.**
This method also has a singular version.
Examples
Replace all attributes from existing objects
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| $res = $index->saveObjects(
[
[
'objectID' => 'myID1',
'firstname' => 'Jimmie',
'lastname' => 'Barninger'
],
[
'objectID' => 'myID2',
'firstname' => 'Warren',
'lastname' => 'Speach'
]
]
);
|
1
2
3
4
5
6
7
8
9
| res = index.save_objects([{
firstname: 'Jimmie',
lastname: 'Barninger',
objectID: 'myID1'
}, {
firstname: 'Warren',
lastname: 'Speach',
objectID: 'myID2'
}])
|
1
2
3
4
5
6
7
8
9
10
11
12
13
| const objects = [{
firstname: 'Jimmie',
lastname: 'Barninger',
objectID: 'myID1'
}, {
firstname: 'Warren',
lastname: 'Speach',
objectID: 'myID2'
}];
index.saveObjects(objects).then(({ objectIDs }) => {
console.log(objectIDs);
});
|
1
2
3
4
| res = index.save_objects([
{'firstname': 'Jimmie', 'lastname': 'Barninger', 'objectID': 'myID1'},
{'firstname': 'Warren', 'lastname': 'Speach', 'objectID': 'myID2'}
])
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| struct Contact: Encodable {
let objectID: ObjectID
let firstname: String
let lastname: String
}
let contacts: [Contact] = [
.init(objectID: "myID1", firstname: "Jimmie", lastname: "Barninger"),
.init(objectID: "myID2", firstname: "Warren", lastname: "Speach"),
]
let replacements = contacts.map {($0.objectID, $0) }
index.replaceObjects(replacements: replacements) { result in
if case .success(let response) = result {
print("Response: \(response)")
}
}
|
1
2
3
4
5
6
7
8
9
10
| List<Contact> contacts = new List<Contact>
{
new Contact { ObjectID = "myID1", Firstname = "Jimmie", Lastname = "Barninger" },
new Contact { ObjectID = "myID2", Firstname = "Warren", Lastname = "Speach" }
};
index.SaveObjects(contacts);
// Asynchronous
await index.SaveObjectsAsync(contacts);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| // Sync version
index.saveObjects(Arrays.asList(
new Contact()
.setFirstName("Jimmie")
.setLastName("Barninger")
.setObjectID("myID"),
new Contact()
.setFirstName("Warren")
.setLastName("Speach")
.setObjectID("myID2")
));
// Async version
index.saveObjectsAsync(Arrays.asList(
new Contact()
.setFirstName("Jimmie")
.setLastName("Barninger")
.setObjectID("myID"),
new Contact()
.setFirstName("Warren")
.setLastName("Speach")
.setObjectID("myID2")
));
|
1
2
3
4
5
6
7
8
9
10
11
12
| type Contact struct {
ObjectID string `json:"objectID"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
}
contacts := []Contact{
{ObjectID: "myID1", Firstname: "Jimmie", Lastname: "Barninger"},
{ObjectID: "myID2", Firstname: "Ray", Lastname: "Charles"},
}
res, err := index.SaveObjects(contacts)
|
1
2
3
4
5
6
| client.execute {
index into "index1" objects Seq(
Contact("myID1", "Jimmie", "Barninger"),
Contact("myID2", "Warren", "Speach")
)
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
| // With JsonObject
val json = listOf(
ObjectID("myID1") to json {
"firstname" to "Jimmie"
"lastname" to "Barninger"
},
ObjectID("myID1") to json {
"firstname" to "Warren"
"lastname" to "Speach"
}
)
index.replaceObjects(json)
// With serializable class
@Serializable
data class Contact(
val firstname: String,
val lastname: String,
override val objectID: ObjectID
) : Indexable
val contacts = listOf(
Contact("Jimmie", "Barninger", ObjectID("myID")),
Contact("Jimmie", "Barninger", ObjectID("myID"))
)
index.replaceObjects(Contact.serializer(), contacts)
|
Replace all attributes of a single object
1
2
3
4
5
6
7
8
| $index->saveObject(
[
'firstname' => 'Jimmie',
'lastname' => 'Barninger',
'city' => 'New York',
'objectID' => 'myID'
]
);
|
1
2
3
4
5
6
| index.save_object({
firstname: 'Jimmie',
lastname: 'Barninger',
city: 'New York',
objectID: 'myID'
})
|
1
2
3
4
5
6
7
8
| index.saveObject({
firstname: 'Jimmie',
lastname: 'Barninger',
city: 'New York',
objectID: 'myID'
}).then(() => {
// done
});
|
1
2
3
4
5
6
| index.save_object({
'firstname': 'Jimmie',
'lastname': 'Barninger',
'city': 'New York',
'objectID': 'myID'}
)
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| struct Contact: Encodable {
let objectID: ObjectID
let firstname: String
let lastname: String
let city: String
}
let contact: Contact = .init(objectID: "myID1", firstname: "Jimmie", lastname: "Barninger", city: "New York")
index.replaceObject(withID: contact.objectID, by: contact) { result in
if case .success(let response) = result {
print("Response: \(response)")
}
}
|
1
2
3
4
| index.SaveObject(new Contact { ObjectID = "myID", Firstname = "Jimmie", Lastname = "Barninger", City = "New York" });
// Asynchronous
await index.SaveObjectAsync(new Contact { ObjectID = "myID", Firstname = "Jimmie", Lastname = "Barninger", City = "New York" });
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| // Sync version
index.saveObject(
new Contact()
.setFirstname("Jimmie")
.setLastname("Barninger")
.setCity("New York")
.setObjectID("myID")
);
// Async version
index.saveObjectAsync(
new Contact()
.setFirstname("Jimmie")
.setLastname("Barninger")
.setCity("New York")
.setObjectID("myID")
);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| type Contact struct {
ObjectID string `json:"objectID"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
City string `json:"city"`
}
contact := Contact{
ObjectID: "myID",
Firstname: "Jimmie",
Lastname: "Barninger",
City: "New York",
}
res, err := index.SaveObject(contact)
|
1
2
3
| client.execute {
index into "index1" `object` Contact("myID", "Jimmie", "Barninger")
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| // With JsonObject
val json = json {
"firstname" to "Jimmie"
"lastname" to "Barninger"
"city" to "New York"
}
index.replaceObject(ObjectID("myID"), json)
// With serializable class
@Serializable
data class Contact(
val firstname: String,
val lastname: String,
val city: String,
override val objectID: ObjectID
) : Indexable
val contact = Contact("Jimmie", "Barninger", "New York", ObjectID("myID"))
index.replaceObject(Contact.serializer(), contact)
|
Replace all attributes from existing objects and send extra HTTP headers
1
2
3
4
| $objects = [/* objects */];
$index->saveObjects($objects, [
'X-Forwarded-For' => '94.228.178.246'
]);
|
1
2
3
4
5
| res = index.save_objects(objects, {
headers: {
'X-Forwarded-For': '94.228.178.246'
}
})
|
1
2
3
4
5
6
7
8
9
| const objects = [/* objects */];
index.saveObjects(objects, {
headers: {
'X-Forwarded-For': '94.228.178.246'
}
}).then(({ objectIDs }) => {
console.log(objectIDs);
});
|
1
2
3
4
5
6
| objects = [
# Objects
]
res = index.save_objects(objects, {
'X-Forwarded-For': '94.228.178.246'
})
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| struct Contact: Encodable {
let objectID: ObjectID
let firstname: String
let lastname: String
}
var requestOptions = RequestOptions()
requestOptions.headers["X-Algolia-User-ID"] = "user123"
let contacts: [Contact] = [
.init(objectID: "myID1", firstname: "Jimmie", lastname: "Barninger"),
.init(objectID: "myID2", firstname: "Warren", lastname: "Speach"),
]
let replacements: [(ObjectID, Contact)] = contacts.map { ($0.objectID, $0) }
index.replaceObjects(replacements: replacements, requestOptions: requestOptions) { result in
if case .success(let response) = result {
print("Response: \(response)")
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| List<Contact> contacts = new List<Contact>
{
new Contact { ObjectID = "myID1", Firstname = "Jimmie", Lastname = "Barninger" },
new Contact { ObjectID = "myID2", Firstname = "Warren", Lastname = "Speach" }
};
RequestOptions requestOptions = new RequestOptions
{
Headers = new Dictionary<string,string>{ { "X-Algolia-User-ID", "user123" } }
};
index.SaveObjects(contacts, requestOptions);
// Asynchronous
await index.SaveObjectsAsync(contacts, requestOptions);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
| List<Contact> contacts = Arrays.asList(
new Contact()
.setObjectID("MyID1")
.setFirstName("Jimmie")
.setLastName("Barninger"),
new Contact()
.setObjectID("MyID2")
.setFirstName("Warren")
.setLastName("Speach"));
// Sync version
index.saveObjects(
contacts,
new RequestOptions().addExtraHeader("X-Algolia-User-ID", "user123")
);
// Async version
index.saveObjectsAsync(
contacts,
new RequestOptions().addExtraHeader("X-Algolia-User-ID", "user123")
);
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| type Contact struct {
ObjectID string `json:"objectID"`
Firstname string `json:"firstname"`
Lastname string `json:"lastname"`
}
contacts := []Contact{
{ObjectID: "myID1", Firstname: "Jimmie", Lastname: "Barninger"},
{ObjectID: "myID2", Firstname: "Ray", Lastname: "Charles"},
}
extraHeaders := opt.ExtraHeaders(map[string]string{
"X-Algolia-User-ID": "userID2",
})
res, err := index.SaveObjects(contacts, extraHeaders)
|
1
2
3
4
5
6
7
8
| client.execute {
index into "index1" objects Seq(
Contact("myID", "Jimmie", "Barninger"),
Contact("myID", "Speach")
) options RequestOptions(
extraHeaders = Some(Map("X-Algolia-User-ID" => "user123"))
)
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
| val json = listOf(
ObjectID("myID1") to json {
"firstname" to "Jimmie"
"lastname" to "Barninger"
},
ObjectID("myID1") to json {
"firstname" to "Warren"
"lastname" to "Speach"
}
)
val requestOptions = requestOptions {
headerAlgoliaUserId(UserID("user123"))
}
index.replaceObjects(json, requestOptions)
|
Override the default batch size
1
2
3
4
5
6
7
| $config = new SearchConfig([
'appId' => 'YourApplicationID',
'apiKey' => 'YourAdminAPIKey',
'batchSize' => 999999,
]);
$client = SearchClient::createWithConfig($config);
|
1
2
3
4
5
6
7
| config = Algolia::Search::Config.new({
application_id: 'YourApplicationID',
api_key: 'YourAdminAPIKey',
batch_size: 999999
})
client = Algolia::Search::Client.create_with_config(config)
|
1
2
3
4
5
6
7
| from algoliasearch.configs import SearchConfig
from algoliasearch.search_client import SearchClient
config = SearchConfig('YourApplicationID', 'YourAdminAPIKey')
config.batch_size = 999999
client = SearchClient.create_with_config(config)
|
1
2
3
| let configuration = SearchConfiguration(applicationID: "YourApplicationID", apiKey: "YourAdminAPIKey")
.set(\.batchSize, to: 999999)
let client = SearchClient(configuration: configuration)
|
1
2
3
4
5
6
| var config = new SearchConfig("YourApplicationID", "YourAdminAPIKey")
{
BatchSize = 999999
};
var client = new SearchClient(config);
|
1
2
3
4
5
6
| SearchConfig config =
new SearchConfig.Builder("YourApplicationID", "YourAdminAPIKey")
.setBatchSize(999999)
.build();
SearchClient client = DefaultSearchClient.create(config);
|
1
2
3
4
5
6
7
| config := search.Configuration{
AppID: "YourApplicationID",
APIKey: "YourAdminAPIKey",
MaxBatchSize: 999999,
}
client := search.NewClientWithConfig(config)
|
Parameters
objects
|
A list of objects to save.
|
autoGenerateObjectIDIfNotExist
|
type: boolean
default: false
Optional
When false , if any of the objects doesn’t contain an objectID , the method throws an error.
When true , if any of the objects doesn’t contain an objectID , the engine automatically assigns one.
|
objectIDKey
|
If specified, for each record, the objectID is set from the value of the specified key.
Only available for PHP.
|
requestOptions
|
type: key-value mapping
default: No request options
Optional
A mapping of requestOptions to send along with the query. In addition to sending extra HTTP headers or setting timeouts, you can use requestOptions to set autoGenerateObjectIDIfNotExist, when using this method.
|
objects âž”
object
An objectID
needs to be specified for each object.
- If the
objectID
exists, the record is replaced
- If the
objectID
doesn’t exist, a record will be created
Response
This section shows the JSON response returned by the API. Since each language encapsulates this response inside objects specific to that language and/or implementation, the actual type in your language might differ from what’s written here. You can view the response in the logs (using the getLogs
method).
Save objects
1
2
3
4
5
6
7
| {
"objectIDs": [
"myObjectID1",
"myObjectID2"
],
"taskID": 678,
}
|
Save object
1
2
3
4
| {
"objectID": "myObjectID1",
"taskID": 678,
}
|
objectIDs
|
List of objectIDs of the saved objects in order. This property is only returned when using save objects.
|
objectID
|
The objectID of the saved object. This property is only returned when using save object.
|
taskID
|
The taskID used with the waitTask method.
|