Update records
For the complete documentation index see: llms.txt
All documentation pages available in markdown.
Applies to
- Aerospike Developer SDK (Java 21+ and Python 3.11+)
- Aerospike Database 8.2.0 or later, unless a section states otherwise
Learn how to update existing records in Aerospike using the Developer SDK. This guide covers updating bins, using operations, conditional updates, and optimistic locking.
Except where noted, snippets on this page use the imports below. A snippet lists additional import lines only when it needs a type not shown here. When this page includes a Complete example section, that block is fully self-contained with every import required to run it.
import com.aerospike.client.sdk.AerospikeException.RecordNotFoundException;import com.aerospike.client.sdk.AerospikeException;import com.aerospike.client.sdk.DataSet;import com.aerospike.client.sdk.HllConfig;import com.aerospike.client.sdk.Record;import com.aerospike.client.sdk.RecordResult;import com.aerospike.client.sdk.RecordStream;import com.aerospike.client.sdk.cdt.MapOrder;
import java.time.Duration;import java.util.List;import time
from aerospike_sdk import DataSet, GenerationError, HllConfigfrom aerospike_sdk.exceptions import AerospikeError, ResultCodeUpdate specific bins
Use update() to modify specific bins in an existing record:
DataSet users = DataSet.of("test", "users");
// Update only the email binsession.update(users.id("user-1")) .bin("email").setTo("newemail@example.com") .execute();
// Update multiple binssession.update(users.id("user-1")) .bin("email").setTo("newemail@example.com") .bin("phone").setTo("+1-555-1234") .bin("updated_at").setTo(System.currentTimeMillis()) .execute();📖 API reference:
DataSet.of(...)|DataSet.id(...)|Session.update(DataSet)|ChainableOperationBuilder.bin(...)|ChainableQueryBuilder.bin(...)|ChainableQueryBuilder.execute()
users = DataSet.of("test", "users")
# Update only the email binawait ( session.update(users.id("user-1")) .bin("email").set_to("newemail@example.com") .execute())
# Update multiple binsawait ( session.update(users.id("user-1")) .bin("email").set_to("newemail@example.com") .bin("phone").set_to("+1-555-1234") .bin("updated_at").set_to(int(time.time() * 1000)) .execute())📖 API reference:
DataSet.of()|DataSet.id()|Session.update()|QueryBuilder.bin()|WriteSegmentBuilder.set_to()|WriteSegmentBuilder.bin()|WriteSegmentBuilder.execute()
See also: Insert vs upsert vs other operations
Increment numbers
Atomically increment numeric values:
DataSet users = DataSet.of("test", "users");
// Increment view count by 1session.update(users.id("user-1")) .bin("view_count").add(1) .execute();
// Increment by a larger amountsession.update(users.id("user-1")) .bin("points").add(100) .execute();
// Decrement (negative increment)session.update(users.id("user-1")) .bin("credits").add(-10) .execute();
// Multiple increments in one operationsession.update(users.id("user-1")) .bin("login_count").add(1) .bin("points").add(5) .bin("last_login").setTo(System.currentTimeMillis()) .execute();📖 API reference:
DataSet.id(...)|Session.update(DataSet)|ChainableOperationBuilder.bin(...)|ChainableQueryBuilder.bin(...)|BinBuilder.add(...)|ChainableQueryBuilder.execute()
users = DataSet.of("test", "users")
# Increment view count by 1await ( session.update(users.id("user-1")) .bin("view_count").add(1) .execute())
# Increment by a larger amountawait ( session.update(users.id("user-1")) .bin("points").add(100) .execute())
# Decrement (negative increment)await ( session.update(users.id("user-1")) .bin("credits").add(-10) .execute())
# Multiple increments in one operationawait ( session.update(users.id("user-1")) .bin("login_count").add(1) .bin("points").add(5) .bin("last_login").set_to(int(time.time() * 1000)) .execute())📖 API reference:
DataSet.of()|DataSet.id()|Session.update()|QueryBuilder.bin()|WriteSegmentBuilder.set_to()|WriteSegmentBuilder.bin()|WriteSegmentBuilder.execute()
Read back after incrementing:
try (RecordStream writeResult = session.update(users.id("user-1")) .bin("view_count").add(1) .bin("view_count").get() .execute()) { Record updated = writeResult.getFirstRecord(); // When multiple operations target the same bin, bins.get() returns an // OpResults list: one entry per operation in order. The add() result is // null; the get() result is the new value. Extract the last element: List<?> ops = (List<?>) updated.bins.get("view_count"); long newViewCount = ((Number) ops.get(ops.size() - 1)).longValue(); System.out.println("view_count: " + newViewCount);}📖 API reference:
DataSet.id(...)|Session.update(DataSet)|ChainableOperationBuilder.bin(...)|ChainableQueryBuilder.bin(...)|BinBuilder.add(...)|ChainableQueryBuilder.execute()|RecordStream.getFirstRecord()|Record.getInt(...)
# Increment first.await ( session.update(users.id("user-1")) .bin("view_count").add(1) .execute())
# Read back the updated value.row = await ( session.query(users.id("user-1")) .bins(["view_count"]) .first_or_raise())record = row.record_or_raise()print(f"view_count: {record.bins['view_count']}")📖 API reference:
DataSet.of()|DataSet.id()|Session.query()|Session.update()|QueryBuilder.bins()|QueryBuilder.bin()|WriteSegmentBuilder.bin()|RecordResult.record_or_raise()|RecordStream.first_or_raise()|RecordStream.close()|QueryBuilder.execute()|WriteSegmentBuilder.execute()
Append to strings
Append text to string bins:
DataSet users = DataSet.of("test", "users");
// Append to a log fieldsession.update(users.id("user-1")) .bin("activity_log").append("\n2024-01-15: Logged in") .execute();
// Prepend (add to beginning)session.update(users.id("user-1")) .bin("activity_log").prepend("Latest: ") .execute();📖 API reference:
DataSet.id(...)|Session.update(DataSet)|ChainableOperationBuilder.bin(...)|ChainableQueryBuilder.bin(...)|ChainableQueryBuilder.execute()
users = DataSet.of("test", "users")
# Append to a log fieldawait ( session.update(users.id("user-1")) .bin("activity_log").append("\n2024-01-15: Logged in") .execute())
# Prepend (add to beginning)await ( session.update(users.id("user-1")) .bin("activity_log").prepend("Latest: ") .execute())📖 API reference:
DataSet.of()|DataSet.id()|Session.update()|WriteSegmentBuilder.execute()
For the full string-manipulation API (substrings, insert/overwrite, case conversion, trimming, padding, and regex replace), see String operations.
Update list/map bins (CDT)
Collection updates use the bin(...) builder with list/map path methods.
This lets you update nested structures without a full read-modify-write cycle.
For the full map/list path API, see CDT operations.
DataSet hotels = DataSet.of("test", "hotels");String key = "hotel:1";
// CD-1 style: set a map entry value.session.update(hotels.id(key)) // setTo puts the entry: it creates `room1`, and the `rooms` map, if missing. .bin("rooms").onMapKey("room1").setTo(150) .execute();
// CD-2 style: one round-trip with range read + count.try (RecordStream rs = session.update(hotels.id(key)) .bin("rooms").onMapKeyRange("room1", "room4").getKeysAndValues() .bin("rooms").onMapKeyRange("room1", "room4").count() .execute()) { var rec = rs.getFirstRecord(); List<?> roomData = rec.getList("rooms"); System.out.println("rooms: " + roomData.get(0)); System.out.println("room count: " + roomData.get(1)); // rangeResult = map entries in range, countResult = count}
// CD-3 style: append to list and read list size in one round-trip.try (RecordStream rs = session.update(hotels.id(key)) .bin("tags").listAppend("vip") .bin("tags").listSize() .execute()) { // One row: the tags bin holds both results; the second is the list size.}
// CD-4 style: nested path update (rooms -> room1 -> rates).session.update(hotels.id(key)) .bin("rooms").onMapKey("room1", MapOrder.KEY_ORDERED) .onMapKey("rates").setTo(110) .execute();📖 API reference:
DataSet.of(...)|Session.update(DataSet)|ChainableOperationBuilder.bin(...)|ChainableQueryBuilder.bin(...)|BinBuilder.onMapKey(...)|BinBuilder.onMapKeyRange(...)|CdtReadOnlyBuilder.getKeysAndValues()|CdtReadOnlyBuilder.count()|ChainableQueryBuilder.execute()|RecordStream.getFirstRecord()|Record.getList(...)
hotels = DataSet.of("test", "hotels")key = hotels.id("hotel:1")
# CD-1 style: set a map entry value.await session.update(key).bin("rooms").on_map_key("room1").set_to(150).execute()
# CD-2 style: one round-trip with range read + count.row = await ( session.update(key) .bin("rooms").on_map_key_range("room1", "room4").get_keys_and_values() .bin("rooms").on_map_key_range("room1", "room4").count() .first_or_raise())record = row.record_or_raise()room_data = record.bins["rooms"]print(f"rooms: {room_data[0]}")print(f"room count: {room_data[1]}")# range_result = map entries in range, count_result = count
# CD-3 style: append to list and read list size in one round-trip.await ( session.update(key) .bin("tags").list_append("vip") .bin("tags").list_size() .execute())
# CD-4 style: nested path update (rooms -> room1 -> rates).await ( session.update(key) .bin("rooms").on_map_key("room1") .on_map_key("rates").set_to(110) .execute())📖 API reference:
DataSet.of()|DataSet.id()|Session.update()|WriteSegmentBuilder.bin()|WriteBinBuilder.on_map_key()|WriteBinBuilder.on_map_key_range()|WriteBinBuilder.list_append()|WriteBinBuilder.list_size()|WriteSegmentBuilder.execute()|RecordStream.first_or_raise()|RecordStream.close()|RecordResult.record_or_raise()
Touch (update metadata only)
“Touch” a record to reset its TTL without changing bin values:
DataSet users = DataSet.of("test", "users");
// Reset TTL to 30 days from nowtry { session.touch(users.id("user-1")) .expireRecordAfter(Duration.ofDays(30)) .execute();} catch (AerospikeException e) { // If server/namespace TTL prerequisites are not met, you can get "Operation not allowed at this time". System.err.println("Touch failed: " + e.getMessage());}📖 API reference:
DataSet.id(...)|Session.touch(Key)|ChainableQueryBuilder.execute()|AerospikeException
users = DataSet.of("test", "users")
# Reset TTL to 30 days from nowtry: await ( session.touch(users.id("user-1")) .expire_record_after_seconds(30 * 24 * 3600) .execute() )except AerospikeError as e: # If server/namespace TTL prerequisites are not met, you can get "Operation not allowed at this time". print(f"Touch failed: {e}")📖 API reference:
DataSet.of()|DataSet.id()|Session.touch()|WriteSegmentBuilder.expire_record_after_seconds()|WriteSegmentBuilder.execute()|AerospikeError
Update many records in the background
A background task updates every record in a set, or every record that matches a filter, in one server-side job. The server runs the job, so your application doesn’t read the records or write them one key at a time.
Call backgroundTask() (Java) or background_task() (Python) on the session, choose update() with the set, add an optional where() filter, and add the bin operations to apply. execute() starts the job and returns a task handle as soon as the job starts. Call waitTillComplete() (Java) or await wait_till_complete() (Python) to block until the server finishes:
DataSet orders = DataSet.of("test", "orders");
ExecuteTask task = session.backgroundTask() .update(orders) .where("$.status == \"shipped\"") .bin("archived").setTo(1) .execute();task.waitTillComplete();📖 API reference:
DataSet.of()|Session.backgroundTask()|BackgroundTaskSession.update()|BackgroundOperationBuilder.where()|BackgroundOperationBuilder.execute()|Task.waitTillComplete()
A string where(...) filter needs Database 8.2 or later. To filter on an earlier server, pass an Exp or Expression to where(...).
orders = DataSet.of("test", "orders")
task = await ( session.background_task() .update(orders) .where('$.status == "shipped"') .bin("archived").set_to(1) .execute())await task.wait_till_complete()📖 API reference:
DataSet.of()|Session.background_task()|BackgroundTaskSession.update()
update() needs at least one bin operation, and the SDK raises ValueError at execute() if you add none.
A background task can’t join a transaction. Calling background_task() on a transactional session raises RuntimeError.
To delete records in the background, see Delete every record in a set.
Change bits in a Blob bin
The bitResize(), bitSet(), and the other bit...() methods (bit_resize() and bit_set() in Python) on a bin builder change a Blob bin at the bit level, on the server. The server applies each change in place, so your application doesn’t read the bytes, change them, and write them back. Chain them like any other bin operation, so one call can resize a bin and then set bits in it. If the bin doesn’t exist, bitResize() creates it, filled with zero bytes. The bin must hold a Blob, and a bit range that extends past the end of the bin fails with a server error, so resize first.
bitResize(byteSize) takes a size in bytes. bitSet(bitOffset, bitSize, value) takes a position and width in bits, and the new bits as a byte[] (bytes in Python). To read bits, use bitCount(bitOffset, bitSize) on a query. It returns how many bits in the range are set to 1.
Key sensor = DataSet.of("test", "sensors").id("sensor:1");
// Resize the flags bin to 4 bytes, then set the first byte (8 bits) to all 1 bits.session.upsert(sensor) .bin("flags").bitResize(4) .bin("flags").bitSet(0, 8, new byte[] {(byte) 0xFF}) .execute();
// Count the 1 bits across all 4 bytes (32 bits).long setBits = session.query(sensor) .bin("flags").bitCount(0, 32) .execute() .getFirstRecord() .getLong("flags");System.out.println(setBits); // 8📖 API reference:
BinBuilder.bitResize(int)|BinBuilder.bitSet(int,int,byte[])|QueryBinBuilder.bitCount(int,int)|RecordStream.getFirstRecord()|Record.getLong(...)
sensor = DataSet.of("test", "sensors").id("sensor:1")
# Resize the flags bin to 4 bytes, then set the first byte (8 bits) to all 1 bits.await ( session.upsert(sensor) .bin("flags").bit_resize(4) .bin("flags").bit_set(0, 8, b"\xff") .execute())
# Count the 1 bits across all 4 bytes (32 bits).row = await session.query(sensor).bin("flags").bit_count(0, 32).first_or_raise()print(row.record_or_raise().bins["flags"]) # 8Other bit operations follow the same pattern. Write operations on a bin builder include bitInsert, bitRemove, bitAnd, bitOr, bitXor, bitNot, bitLshift, bitRshift, bitAdd, bitSubtract, and bitSetInt. Read operations on a query include bitGet, bitGetInt, bitLscan, and bitRscan. Python uses the snake case names, such as bit_insert and bit_get.
Delete bins
Remove specific bins from a record without deleting the record. Note: if all bins of a record are removed, the record is automatically deleted:
DataSet users = DataSet.of("test", "users");
// Remove the phone binsession.update(users.id("user-1")) .bin("phone").remove() .execute();
// Remove multiple binssession.update(users.id("user-1")) .bin("phone").remove() .bin("fax").remove() .bin("pager").remove() .execute();📖 API reference:
DataSet.id(...)|Session.update(DataSet)|ChainableOperationBuilder.bin(...)|ChainableQueryBuilder.bin(...)|BinBuilder.remove()|ChainableQueryBuilder.execute()
users = DataSet.of("test", "users")
# Remove the phone binawait ( session.update(users.id("user-1")) .bin("phone").remove() .execute())
# Remove multiple binsawait ( session.update(users.id("user-1")) .bin("phone").remove() .bin("fax").remove() .bin("pager").remove() .execute())📖 API reference:
DataSet.of()|DataSet.id()|Session.update()|WriteSegmentBuilder.execute()
Conditional update (optimistic locking)
Use generation checks to prevent concurrent update conflicts:
DataSet users = DataSet.of("test", "users");
// Read current recordRecordStream readStream = session.query(users.id("user-1")).execute();Record user = readStream.getFirstRecord();
int currentGeneration = user.generation;
// Update only if generation hasn't changedtry { session.update(users.id("user-1")) .bin("email").setTo("newemail@example.com") .ensureGenerationIs(currentGeneration) .execute(); System.out.println("Update successful");} catch (AerospikeException.GenerationException e) { System.out.println("Record was modified by another process");}📖 API reference:
DataSet.id(...)|Session.update(DataSet)|Session.query(Key)|ChainableOperationBuilder.bin(...)|ChainableQueryBuilder.bin(...)|ChainableQueryBuilder.execute()|RecordStream.getFirstRecord()
users = DataSet.of("test", "users")
# Read current recordrow = await session.query(users.id("user-1")).first_or_raise()user = row.record_or_raise()
current_generation = user.generation
# Update only if generation hasn't changedtry: await ( session.update(users.id("user-1")) .bin("email").set_to("newemail@example.com") .ensure_generation_is(current_generation) .execute() ) print("Update successful")except GenerationError: print("Record was modified by another process")📖 API reference:
DataSet.of()|DataSet.id()|Session.query()|Session.update()|QueryBuilder.bin()|WriteSegmentBuilder.set_to()|WriteSegmentBuilder.bin()|WriteSegmentBuilder.ensure_generation_is()|RecordResult.record_or_raise()|RecordStream.first_or_raise()|QueryBuilder.execute()|WriteSegmentBuilder.execute()
Optimistic locking pattern
public void updateWithRetry(DataSet users, String userId, int maxRetries) { for (int attempt = 0; attempt < maxRetries; attempt++) { // Read current state RecordStream rs = session.query(users.id(userId)).execute(); Record user = rs.getFirstRecord();
int newBalance = user.getInt("balance") + 100;
try { // Attempt update with generation check session.update(users.id(userId)) .bin("balance").setTo(newBalance) .ensureGenerationIs(user.generation) .execute(); return; // Success } catch (AerospikeException.GenerationException e) { // Retry on conflict System.out.println("Conflict, retrying..."); } } throw new RuntimeException("Max retries exceeded");}📖 API reference:
Session.update(DataSet)|Session.query(Key)|ChainableOperationBuilder.bin(...)|ChainableQueryBuilder.bin(...)|ChainableQueryBuilder.execute()|RecordStream.getFirstRecord()|Record.getInt(...)
async def update_with_retry(users: DataSet, user_id: str, max_retries: int) -> None: for attempt in range(max_retries): # Read current state row = await session.query(users.id(user_id)).first_or_raise() user = row.record_or_raise()
new_balance = user.bins["balance"] + 100
try: # Attempt update with generation check await ( session.update(users.id(user_id)) .bin("balance").set_to(new_balance) .ensure_generation_is(user.generation) .execute() ) return # Success except GenerationError: # Retry on conflict print("Conflict, retrying...") raise RuntimeError("Max retries exceeded")📖 API reference:
Session.query()|Session.update()|QueryBuilder.bin()|WriteSegmentBuilder.set_to()|WriteSegmentBuilder.bin()|WriteSegmentBuilder.ensure_generation_is()|RecordResult.record_or_raise()|RecordStream.first_or_raise()|QueryBuilder.execute()|WriteSegmentBuilder.execute()
Update only if exists
Ensure the record exists before updating:
DataSet users = DataSet.of("test", "users");
try { session.update(users.id("user-1")) .bin("email").setTo("newemail@example.com") .execute();} catch (RecordNotFoundException e) { System.out.println("Record doesn't exist");}📖 API reference:
DataSet.id(...)|Session.update(DataSet)|ChainableOperationBuilder.bin(...)|ChainableQueryBuilder.bin(...)|ChainableQueryBuilder.execute()
users = DataSet.of("test", "users")
try: await ( session.update(users.id("user-1")) .bin("email").set_to("newemail@example.com") .execute() )except AerospikeError as e: if e.result_code != ResultCode.KEY_NOT_FOUND_ERROR: raise print("Record doesn't exist")📖 API reference:
DataSet.of()|DataSet.id()|Session.update()|QueryBuilder.bin()|WriteSegmentBuilder.set_to()|WriteSegmentBuilder.bin()|WriteSegmentBuilder.execute()
Replace all bins (atomic full-record overwrite)
Use session.replace(key) to atomically overwrite a record with a new set of bins, removing any bins that were on the record before. This is the correct way to do a full-record replace in a single write without reading first. The record is created if it does not already exist.
DataSet users = DataSet.of("test", "users");
// Atomically replace all bins; old bins like "active" are removed.// session.replace() creates the record if it does not already exist.session.replace(users.id("user-1")) .bin("name").setTo("Alice Smith") .bin("age").setTo(31) .execute();📖 API reference:
DataSet.of(...)|DataSet.id(...)|Session.replace(DataSet)|ChainableOperationBuilder.bin(...)|BinBuilder.setTo(...)|ChainableQueryBuilder.execute()
users = DataSet.of("test", "users")
# Atomically replace all bins; old bins like "active" are removed.# session.replace() creates the record if it does not already exist.await ( session.replace(users.id("user-1")) .put({"name": "Alice Smith", "age": 31}) .execute())📖 API reference:
Session.replace()|WriteSegmentBuilder.put()|WriteSegmentBuilder.execute()
To require that the record already exists instead of creating it, use replace_if_exists(...):
DataSet users = DataSet.of("test", "users");
// Fails if the record does not already exist; otherwise behaves like replace().session.replaceIfExists(users.id("user-1")) .bin("name").setTo("Alice Smith") .bin("age").setTo(31) .execute();📖 API reference:
Session.replaceIfExists(Key)|ChainableOperationBuilder.bin(...)|BinBuilder.setTo(...)|ChainableQueryBuilder.execute()
users = DataSet.of("test", "users")
# Fails if the record does not already exist; otherwise behaves like replace().await ( session.replace_if_exists(users.id("user-1")) .put({"name": "Alice Smith", "age": 31}) .execute())📖 API reference:
Session.replace_if_exists()|WriteSegmentBuilder.put()|WriteSegmentBuilder.execute()
On a missing key this raises (RecordNotFoundError in Python / an AerospikeException with a not-found result code in Java) instead of creating the record.
GeoJSON bins
Write a bin as a GeoJSON value. The server stores a GEOJSON particle type (not a string), which makes the bin eligible for GEO2DSPHERE indexing and geoCompare(...) queries.
DataSet places = DataSet.of("test", "places");
session.upsert(places.id("space_needle")) .bin("loc").setToGeoJson("{\"type\":\"Point\",\"coordinates\":[-122.349,47.620]}") .execute();📖 API reference:
BinBuilder.setToGeoJson(...)
places = DataSet.of("test", "places")
await ( session.upsert(places.id("space_needle")) .bin("loc").set_to_geo_json('{"type":"Point","coordinates":[-122.349,47.620]}') .execute())📖 API reference:
WriteBinBuilder.set_to_geo_json()
HyperLogLog (HLL) bins
Use HllConfig to describe sketch precision, then initialize and add values on a bin:
DataSet visitors = DataSet.of("test", "visitors");
session.upsert(visitors.id("day_1")) .bin("h").hllInit(HllConfig.of(14)) .bin("h").hllAdd(List.of("user-1", "user-2", "user-3")) .execute();
// Create the sketch only if it doesn't exist; no-op if it already does.session.upsert(visitors.id("day_2")) .bin("h").hllInit(HllConfig.of(14), opt -> opt.createOnly().noFail()) .execute();📖 API reference:
HllConfig.of(...)|BinBuilder.hllInit(...)|BinBuilder.hllAdd(...)|HllWriteOptions
visitors = DataSet.of("test", "visitors")
await ( session.upsert(visitors.id("day_1")) .bin("h").hll_init(HllConfig.of(14)) .bin("h").hll_add(["user-1", "user-2", "user-3"]) .execute())
# Create the sketch only if it doesn't exist; no-op if it already does.await ( session.upsert(visitors.id("day_2")) .bin("h").hll_init(HllConfig.of(14), create_only=True, no_fail=True) .execute())📖 API reference:
HllConfig|WriteSegmentBuilder.bin()|WriteBinBuilder.hll_init()|WriteBinBuilder.hll_add()
Complete example
This example is self-contained—it lists every import needed to run standalone.
import com.aerospike.client.sdk.Cluster;import com.aerospike.client.sdk.ClusterDefinition;import com.aerospike.client.sdk.DataSet;import com.aerospike.client.sdk.Record;import com.aerospike.client.sdk.RecordResult;import com.aerospike.client.sdk.RecordStream;import com.aerospike.client.sdk.Session;import com.aerospike.client.sdk.policy.Behavior;
public class UpdateRecordsExample { public static void main(String[] args) { try (Cluster cluster = new ClusterDefinition("localhost", 3000).connect()) { Session session = cluster.createSession(Behavior.DEFAULT); DataSet users = DataSet.of("test", "users"); String key = "update-example-user";
// Seed data so the example is repeatable. session.upsert(users) .bins("name", "login_count", "points") .id(key).values("Alice Smith", 0, 0) .execute();
// Simple update session.update(users.id(key)) .bin("status").setTo("active") .bin("updated_at").setTo(System.currentTimeMillis()) .execute();
// Increment counters session.update(users.id(key)) .bin("login_count").add(1) .bin("points").add(10) .execute();
// Conditional update with generation check RecordStream rs = session.query(users.id(key)).execute(); Record user = rs.getFirstRecord(); session.update(users.id(key)) .bin("verified").setTo(true) .ensureGenerationIs(user.generation) .execute();
System.out.println("All updates completed!"); } }}📖 API reference:
ClusterDefinition(String,int)|ClusterDefinition.connect()|Cluster.createSession(Behavior)|Cluster.close()|DataSet.of(...)|Session.upsert(DataSet)|Session.update(DataSet)|Session.query(Key)|OperationObjectBuilder.bins(...)|IdValuesBuilder.id(...)|IdValuesRowBuilder.values(...)|ChainableOperationBuilder.bin(...)|ChainableQueryBuilder.bin(...)|BinBuilder.add(...)|ChainableQueryBuilder.execute()|RecordStream.getFirstRecord()
import asyncioimport timefrom aerospike_sdk import Behavior, ClusterDefinition, DataSet
async def main(): async with ClusterDefinition("localhost", 3000).connect() as cluster: session = cluster.create_session(Behavior.DEFAULT) users = DataSet.of("test", "users") key = users.id("update-example-user")
# Seed data so the example is repeatable. await session.upsert(key).put( {"name": "Alice Smith", "login_count": 0, "points": 0} ).execute()
# Simple update await ( session.update(key) .bin("status").set_to("active") .bin("updated_at").set_to(int(time.time() * 1000)) .execute() )
# Increment counters await ( session.update(key) .bin("login_count").add(1) .bin("points").add(10) .execute() )
# Conditional update with generation check row = await session.query(key).first_or_raise() user = row.record_or_raise() await ( session.update(key) .bin("verified").set_to(True) .ensure_generation_is(user.generation) .execute() )
print("All updates completed!")
if __name__ == "__main__": asyncio.run(main())📖 API reference:
ClusterDefinition|ClusterDefinition.connect()|Cluster.create_session()|DataSet.of()|DataSet.id()|Behavior.DEFAULT|Session.query()|Session.upsert()|Session.update()|QueryBuilder.bin()|WriteSegmentBuilder.put()|WriteSegmentBuilder.set_to()|WriteSegmentBuilder.bin()|WriteSegmentBuilder.ensure_generation_is()|RecordResult.record_or_raise()|RecordStream.first_or_raise()|QueryBuilder.execute()|WriteSegmentBuilder.execute()
API reference summary
| Method | Description |
|---|---|
update() | Update an existing record, fails if the record doesn’t exist |
replace() / replace_if_exists() | Atomic full-record overwrite (drops bins not in the call) |
touch() | Update metadata/TTL only |
.bin(name).add(delta) (Java and Python) | Atomically increment a numeric bin |
.bin(name).setToGeoJson(json) (Java) · .bin(name).set_to_geo_json(json) (Python) | Write a GeoJSON bin |
.bin(name).hllInit(...) / .hllAdd(...) (Java) · .bin(name).hll_init(...) / .hll_add(...) (Python) | HyperLogLog sketch operations |
.bin(name).append(text) / .prepend(text) (Java and Python) | Append or prepend a string bin |
.bin(name).bitResize(bytes) / .bitSet(offset, size, value) (Java) · .bit_resize(...) / .bit_set(...) (Python) | Resize a Blob bin or set a range of its bits |
.bin(name).remove() (Java and Python) | Remove a bin |
.ensureGenerationIs(gen) (Java) · .ensure_generation_is(gen) (Python) | Conditional update |
Next steps
Delete Records
Remove records from the database.
Batch Operations
Update multiple records efficiently.
Error Handling
Handle update conflicts and errors.