> ## Documentation Index
> Fetch the complete documentation index at: https://algolia.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Incremental updates

> How to keep your data in sync with Algolia.

export const Records = () => <Tooltip tip="A record is a searchable object in an Algolia index. Each record consists of named attributes." cta="Algolia records" href="/doc/guides/sending-and-managing-data/prepare-your-data#algolia-records">
    records
  </Tooltip>;

export const Index = () => <Tooltip tip="An Algolia index is a searchable dataset that consists of records and configuration settings. These settings define how the records are searched and ranked.">
    index
  </Tooltip>;

After initially uploading your data,
*you need to keep your  <Index /> up to date as the data changes*\*.

One way of doing so is with incremental updates,
by tracking changes and forwarding them to Algolia.
Whenever you add, edit, or delete data from your source,
update the corresponding <Records /> so they reflect the latest state of your data.

## Track each record with a unique identifier

To perform incremental updates, you need to declare a unique identifier for each record so you can track what data matches what record.
This identifier should map to a "key" you store on your side.

You need to store the unique identifier in the `objectID` attribute.

## Add records

Whenever you add new data in your data source,
you can add them to Algolia with the [`saveObjects`](/doc/libraries/sdk/methods/search/save-objects) method.

To run the code examples on this page, [install the latest API client](/doc/libraries/sdk/install).

<CodeGroup>
  ```cs C# theme={"system"}
  var response = await client.SaveObjectsAsync(
    "INDEX_NAME",
    new List<Object>
    {
      new Dictionary<string, string> { { "objectID", "1" }, { "name", "Adam" } },
      new Dictionary<string, string> { { "objectID", "2" }, { "name", "Benoit" } },
    }
  );
  ```

  ```go Go theme={"system"}
  response, err := client.SaveObjects(
    "INDEX_NAME",
    []map[string]any{{"objectID": "1", "name": "Adam"}, {"objectID": "2", "name": "Benoit"}})
  if err != nil {
    // handle the eventual error
    panic(err)
  }
  ```

  ```java Java theme={"system"}
  List response = client.saveObjects(
    "INDEX_NAME",
    Arrays.asList(
      new HashMap() {
        {
          put("objectID", "1");
          put("name", "Adam");
        }
      },
      new HashMap() {
        {
          put("objectID", "2");
          put("name", "Benoit");
        }
      }
    )
  );
  ```

  ```js JavaScript theme={"system"}
  const response = await client.saveObjects({
    indexName: 'cts_e2e_saveObjects_javascript',
    objects: [
      { objectID: '1', name: 'Adam' },
      { objectID: '2', name: 'Benoit' },
    ],
  });
  ```

  ```kotlin Kotlin theme={"system"}
  var response =
    client.saveObjects(
      indexName = "INDEX_NAME",
      objects =
        listOf(
          buildJsonObject {
            put("objectID", JsonPrimitive("1"))
            put("name", JsonPrimitive("Adam"))
          },
          buildJsonObject {
            put("objectID", JsonPrimitive("2"))
            put("name", JsonPrimitive("Benoit"))
          },
        ),
    )
  ```

  ```php PHP theme={"system"}
  $response = $client->saveObjects(
      'INDEX_NAME',
      [
          ['objectID' => '1',
              'name' => 'Adam',
          ],

          ['objectID' => '2',
              'name' => 'Benoit',
          ],
      ],
  );
  ```

  ```python Python theme={"system"}
  response = client.save_objects(
      index_name="INDEX_NAME",
      objects=[
          {
              "objectID": "1",
              "name": "Adam",
          },
          {
              "objectID": "2",
              "name": "Benoit",
          },
      ],
  )
  ```

  ```ruby Ruby theme={"system"}
  response = client.save_objects(
    "INDEX_NAME",
    [{objectID: "1", name: "Adam"}, {objectID: "2", name: "Benoit"}]
  )
  ```

  ```scala Scala theme={"system"}
  val response = Await.result(
    client.saveObjects(
      indexName = "INDEX_NAME",
      objects = Seq(
        JObject(List(JField("objectID", JString("1")), JField("name", JString("Adam")))),
        JObject(List(JField("objectID", JString("2")), JField("name", JString("Benoit"))))
      )
    ),
    Duration(100, "sec")
  )
  ```

  ```swift Swift theme={"system"}
  let response = try await client.saveObjects(
      indexName: "INDEX_NAME",
      objects: [["objectID": "1", "name": "Adam"], ["objectID": "2", "name": "Benoit"]]
  )
  ```
</CodeGroup>

## Update records

You can update records in two ways:

* Fully replace the old record with a new one
* Update only a subset of the record (attributes) with new data

### Replace old records

When saving a record in Algolia, if a record with the specified `objectID` already exists in the index,
the engine replaces it.
You can replace an existing record by using the `saveObjects` method and specifying the `objectID`.
This technique is useful when you're updating data in a single place in your system, or when you don't know what changed.

<CodeGroup>
  ```cs C# theme={"system"}
  var response = await client.SaveObjectsAsync(
    "INDEX_NAME",
    new List<Object>
    {
      new Dictionary<string, string> { { "objectID", "1" }, { "name", "Adam" } },
      new Dictionary<string, string> { { "objectID", "2" }, { "name", "Benoit" } },
    }
  );
  ```

  ```go Go theme={"system"}
  response, err := client.SaveObjects(
    "INDEX_NAME",
    []map[string]any{{"objectID": "1", "name": "Adam"}, {"objectID": "2", "name": "Benoit"}})
  if err != nil {
    // handle the eventual error
    panic(err)
  }
  ```

  ```java Java theme={"system"}
  List response = client.saveObjects(
    "INDEX_NAME",
    Arrays.asList(
      new HashMap() {
        {
          put("objectID", "1");
          put("name", "Adam");
        }
      },
      new HashMap() {
        {
          put("objectID", "2");
          put("name", "Benoit");
        }
      }
    )
  );
  ```

  ```js JavaScript theme={"system"}
  const response = await client.saveObjects({
    indexName: 'cts_e2e_saveObjects_javascript',
    objects: [
      { objectID: '1', name: 'Adam' },
      { objectID: '2', name: 'Benoit' },
    ],
  });
  ```

  ```kotlin Kotlin theme={"system"}
  var response =
    client.saveObjects(
      indexName = "INDEX_NAME",
      objects =
        listOf(
          buildJsonObject {
            put("objectID", JsonPrimitive("1"))
            put("name", JsonPrimitive("Adam"))
          },
          buildJsonObject {
            put("objectID", JsonPrimitive("2"))
            put("name", JsonPrimitive("Benoit"))
          },
        ),
    )
  ```

  ```php PHP theme={"system"}
  $response = $client->saveObjects(
      'INDEX_NAME',
      [
          ['objectID' => '1',
              'name' => 'Adam',
          ],

          ['objectID' => '2',
              'name' => 'Benoit',
          ],
      ],
  );
  ```

  ```python Python theme={"system"}
  response = client.save_objects(
      index_name="INDEX_NAME",
      objects=[
          {
              "objectID": "1",
              "name": "Adam",
          },
          {
              "objectID": "2",
              "name": "Benoit",
          },
      ],
  )
  ```

  ```ruby Ruby theme={"system"}
  response = client.save_objects(
    "INDEX_NAME",
    [{objectID: "1", name: "Adam"}, {objectID: "2", name: "Benoit"}]
  )
  ```

  ```scala Scala theme={"system"}
  val response = Await.result(
    client.saveObjects(
      indexName = "INDEX_NAME",
      objects = Seq(
        JObject(List(JField("objectID", JString("1")), JField("name", JString("Adam")))),
        JObject(List(JField("objectID", JString("2")), JField("name", JString("Benoit"))))
      )
    ),
    Duration(100, "sec")
  )
  ```

  ```swift Swift theme={"system"}
  let response = try await client.saveObjects(
      indexName: "INDEX_NAME",
      objects: [["objectID": "1", "name": "Adam"], ["objectID": "2", "name": "Benoit"]]
  )
  ```
</CodeGroup>

### Update a subset of the record

When you don't need to replace the entire record,
you can also update specific attributes of a record.
This is useful when you know which attribute to update,
but you don't know the other attributes,
for example, when different systems manage different aspects of your data.

For this, you can use the [`partialUpdateObjects`](/doc/libraries/sdk/methods/search/partial-update-objects) method and only pass the changed data.
Anything you don't specify remains untouched.

<CodeGroup>
  ```cs C# theme={"system"}
  var response = await client.PartialUpdateObjectsAsync(
    "INDEX_NAME",
    new List<Object>
    {
      new Dictionary<string, string> { { "objectID", "1" }, { "name", "Adam" } },
      new Dictionary<string, string> { { "objectID", "2" }, { "name", "Benoit" } },
    },
    true
  );
  ```

  ```go Go theme={"system"}
  response, err := client.PartialUpdateObjects(
    "INDEX_NAME",
    []map[string]any{{"objectID": "1", "name": "Adam"}, {"objectID": "2", "name": "Benoit"}}, search.WithCreateIfNotExists(true))
  if err != nil {
    // handle the eventual error
    panic(err)
  }
  ```

  ```java Java theme={"system"}
  List response = client.partialUpdateObjects(
    "INDEX_NAME",
    Arrays.asList(
      new HashMap() {
        {
          put("objectID", "1");
          put("name", "Adam");
        }
      },
      new HashMap() {
        {
          put("objectID", "2");
          put("name", "Benoit");
        }
      }
    ),
    true
  );
  ```

  ```js JavaScript theme={"system"}
  const response = await client.partialUpdateObjects({
    indexName: 'cts_e2e_partialUpdateObjects_javascript',
    objects: [
      { objectID: '1', name: 'Adam' },
      { objectID: '2', name: 'Benoit' },
    ],
    createIfNotExists: true,
  });
  ```

  ```kotlin Kotlin theme={"system"}
  var response =
    client.partialUpdateObjects(
      indexName = "INDEX_NAME",
      objects =
        listOf(
          buildJsonObject {
            put("objectID", JsonPrimitive("1"))
            put("name", JsonPrimitive("Adam"))
          },
          buildJsonObject {
            put("objectID", JsonPrimitive("2"))
            put("name", JsonPrimitive("Benoit"))
          },
        ),
      createIfNotExists = true,
    )
  ```

  ```php PHP theme={"system"}
  $response = $client->partialUpdateObjects(
      'INDEX_NAME',
      [
          ['objectID' => '1',
              'name' => 'Adam',
          ],

          ['objectID' => '2',
              'name' => 'Benoit',
          ],
      ],
      true,
  );
  ```

  ```python Python theme={"system"}
  response = client.partial_update_objects(
      index_name="INDEX_NAME",
      objects=[
          {
              "objectID": "1",
              "name": "Adam",
          },
          {
              "objectID": "2",
              "name": "Benoit",
          },
      ],
      create_if_not_exists=True,
  )
  ```

  ```ruby Ruby theme={"system"}
  response = client.partial_update_objects(
    "INDEX_NAME",
    [{objectID: "1", name: "Adam"}, {objectID: "2", name: "Benoit"}],
    true
  )
  ```

  ```scala Scala theme={"system"}
  val response = Await.result(
    client.partialUpdateObjects(
      indexName = "INDEX_NAME",
      objects = Seq(
        JObject(List(JField("objectID", JString("1")), JField("name", JString("Adam")))),
        JObject(List(JField("objectID", JString("2")), JField("name", JString("Benoit"))))
      ),
      createIfNotExists = true
    ),
    Duration(100, "sec")
  )
  ```

  ```swift Swift theme={"system"}
  let response = try await client.partialUpdateObjects(
      indexName: "INDEX_NAME",
      objects: [["objectID": "1", "name": "Adam"], ["objectID": "2", "name": "Benoit"]],
      createIfNotExists: true
  )
  ```
</CodeGroup>

## Delete records

Whenever you delete data in your data source,
you can delete the corresponding record from Algolia with [`deleteObjects`](/doc/libraries/sdk/methods/search/delete-objects).

<CodeGroup>
  ```cs C# theme={"system"}
  var response = await client.DeleteObjectsAsync(
    "INDEX_NAME",
    new List<string> { "1", "2" }
  );
  ```

  ```go Go theme={"system"}
  response, err := client.DeleteObjects(
    "INDEX_NAME",
    []string{"1", "2"})
  if err != nil {
    // handle the eventual error
    panic(err)
  }
  ```

  ```java Java theme={"system"}
  List response = client.deleteObjects("INDEX_NAME", Arrays.asList("1", "2"));
  ```

  ```js JavaScript theme={"system"}
  const response = await client.deleteObjects({ indexName: 'INDEX_NAME', objectIDs: ['1', '2'] });
  ```

  ```kotlin Kotlin theme={"system"}
  var response =
    client.deleteObjects(indexName = "INDEX_NAME", objectIDs = listOf("1", "2"))
  ```

  ```php PHP theme={"system"}
  $response = $client->deleteObjects(
      'INDEX_NAME',
      [
          '1',

          '2',
      ],
  );
  ```

  ```python Python theme={"system"}
  response = client.delete_objects(
      index_name="INDEX_NAME",
      object_ids=[
          "1",
          "2",
      ],
  )
  ```

  ```ruby Ruby theme={"system"}
  response = client.delete_objects("INDEX_NAME", ["1", "2"])
  ```

  ```scala Scala theme={"system"}
  val response = Await.result(
    client.deleteObjects(
      indexName = "INDEX_NAME",
      objectIDs = Seq("1", "2")
    ),
    Duration(100, "sec")
  )
  ```

  ```swift Swift theme={"system"}
  let response = try await client.deleteObjects(indexName: "INDEX_NAME", objectIDs: ["1", "2"])
  ```
</CodeGroup>

### Delete by query

Sometimes, you may need to delete all records matching a certain filter. Back to the book example, if you stop selling books from a specific publisher, you might want to delete all records matching this `publisher` in your index. To do this, you can use the [`deleteBy`](/doc/libraries/sdk/methods/search/delete-by) method.

<Note>
  The [`deleteBy`](/doc/libraries/sdk/methods/search/delete-by) method is an expensive operation for the engine.
  For better performance, use the [`deleteObjects`](/doc/libraries/sdk/methods/search/delete-objects) method instead.
</Note>

<CodeGroup>
  ```cs C# theme={"system"}
  var response = await client.DeleteByAsync(
    "INDEX_NAME",
    new DeleteByParams { Filters = "brand:brandName" }
  );
  ```

  ```dart Dart theme={"system"}
  final response = await client.deleteBy(
    indexName: "INDEX_NAME",
    deleteByParams: DeleteByParams(
      filters: "brand:brandName",
    ),
  );
  ```

  ```go Go theme={"system"}
  response, err := client.DeleteBy(client.NewApiDeleteByRequest(
    "INDEX_NAME",
    search.NewEmptyDeleteByParams().SetFilters("brand:brandName")))
  if err != nil {
    // handle the eventual error
    panic(err)
  }
  ```

  ```java Java theme={"system"}
  UpdatedAtResponse response = client.deleteBy("INDEX_NAME", new DeleteByParams().setFilters("brand:brandName"));
  ```

  ```js JavaScript theme={"system"}
  const response = await client.deleteBy({ indexName: 'theIndexName', deleteByParams: { filters: 'brand:brandName' } });
  ```

  ```kotlin Kotlin theme={"system"}
  var response =
    client.deleteBy(
      indexName = "INDEX_NAME",
      deleteByParams = DeleteByParams(filters = "brand:brandName"),
    )
  ```

  ```php PHP theme={"system"}
  $response = $client->deleteBy(
      'INDEX_NAME',
      ['filters' => 'brand:brandName',
      ],
  );
  ```

  ```python Python theme={"system"}
  response = client.delete_by(
      index_name="INDEX_NAME",
      delete_by_params={
          "filters": "brand:brandName",
      },
  )
  ```

  ```ruby Ruby theme={"system"}
  response = client.delete_by("INDEX_NAME", Algolia::Search::DeleteByParams.new(filters: "brand:brandName"))
  ```

  ```scala Scala theme={"system"}
  val response = Await.result(
    client.deleteBy(
      indexName = "INDEX_NAME",
      deleteByParams = DeleteByParams(
        filters = Some("brand:brandName")
      )
    ),
    Duration(100, "sec")
  )
  ```

  ```swift Swift theme={"system"}
  let response = try await client.deleteBy(
      indexName: "INDEX_NAME",
      deleteByParams: DeleteByParams(filters: "brand:brandName")
  )
  ```
</CodeGroup>

<Note>
  Any attribute you're using to delete by needs to be in your [`searchableAttributes`](/doc/api-reference/api-parameters/searchableAttributes).
</Note>
