Bin operations
This page describes bin operations that refer specifically to the operate command. Each bin operation works on a specified bin of the target record.
Overview
Aerospike records contain one or more bins of potentially different data types. Nested Lists and Maps, also called collection data types (or CDTs) may be combined to implement a complex data structure as a document. To service these potentially-complex documents of data, every Aerospike client provides the following method:
operate
Executes multiple bin operations atomically and in isolation as a single record command. Operations include the bin read and write operations, and any operation on a data type which is stored in a bin. Examples are add on integer bins, HLL operations on HyperLogLog bins, bitwise operations on Blob (Bytes) bins, or the large API of operations on list and map bins.
One of the arguments to the operate
method is an ordered list of bin operations to execute. The syntax used by Aerospike clients varies by programming language. Unlike a record get
operation, which returns an Aerospike record, operate returns output from each sub-operation per bin. This is useful to confirm transaction processing and to troubleshoot logic that results in unexpected transaction success or failures.
The operate
command acquires the record lock and executes the bin operations atomically and in isolation.
The following is the comprehensive list of bin operations that can be part of a transaction using operate. The table below contains either the operations or a link to the comprehensive list of operations for each data type.
Data Type | Bin operation | Description |
---|---|---|
All | op_put | Upsert (create or update) a bin. Also called write . |
All | op_get | Read a bin. Also called read . |
All | op_touch | Increase the generation counter for a record. |
All | op_delete | Remove a record from the database. Generates a tombstone when you use the durable delete policy. |
Integer Float | op_add | Add (or subtract) a value. Used to implement counters. Also called increment . |
String | op_append op_prepend | Modify a string. |
List | For a list of all List Operations, see Collection Data Types: Lists. | |
Map | For a list of all Map Operations, see Collection Data Types: Maps. | |
Blob/ Bytes | For a list of all Blob/Byte Operations, see Data Types: Blob/Bytes. | |
HLL | For a list of all HyperLogLog Operations, see Data Types: HyperLogLog. | |
Geo | For a list of all Geospatial Operations, see Data Types: Geospatial. |
Filtering transactions
A transaction can be conditionally applied, based on the result of a filter expression. If the filter expression evaluates to true, the transaction will execute.
Code example of the operate command
The following example combines read and update operations on the same record into one command.
- Java
- Python
import java.util.HashMap;
import java.util.Map;
import com.aerospike.client.AerospikeClient;
import com.aerospike.client.Bin;
import com.aerospike.client.Key;
import com.aerospike.client.Operation;
import com.aerospike.client.Record;
import com.aerospike.client.Value;
import com.aerospike.client.policy.RecordExistsAction;
import com.aerospike.client.policy.WritePolicy;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
AerospikeClient client = new AerospikeClient("localhost", 3000);
// Aerospike namespace, set, and key_id to be used for the Aerospike key
String namespace = "sandbox";
String set = "ufo";
int key_id = 5231;
// Create key
Key key = new Key(namespace, set, key_id);
// Example JSON string
String sighting = "{\"sighting\":{\"occurred\":20200912,\"reported\":20200916,\"posted\":20201105,\"report\":{\"city\":\"Kirkland\",\"duration\":\"~30 minutes\",\"shape\":[\"circle\"],\"state\":\"WA\",\"summary\":\"4 rotating orange lights in the Kingsgate area above the Safeway. Around 9pm the power went out in the Kingsgate area. Four lights were spotted rotating above the local Safeway and surrounding streets. They were rotating fast but staying relatively in the same spots. Also described as orange lights. About thirty minutes later they disappeared. The second they disappeared the power was restored. Later a station of police from Woodinville and Kirkland came to guard the street where it happened. They wouldn't let anyone go past the street, putting out search lights and flare signals so people couldn't drive past Safeway. The police also would not let people walk past to go home.\"},\"location\":\"\\\"{\\\"type\\\":\\\"Point\\\",\\\"coordinates\\\":[-122.1966441,47.69328259]}\\\"\"}}";
// Convert string to Java Map
Map<String, Map<String, Object>> sightingMap = new Gson().fromJson(sighting, new TypeToken<HashMap<String, HashMap<String, Object>>>(){}.getType());
// Create bins from map
Bin[] bins = {
new Bin("occurred", Value.get(sightingMap.get("sighting").get("occurred"))),
new Bin("reported", Value.get(sightingMap.get("sighting").get("reported"))),
new Bin("posted", Value.get(sightingMap.get("sighting").get("posted"))),
new Bin("report", Value.get(sightingMap.get("sighting").get("report"))),
};
// Create write policy
WritePolicy writePolicy = client.copyWritePolicyDefault();
writePolicy.recordExistsAction = RecordExistsAction.UPDATE;
writePolicy.respondAllOps = true;
// Write record
client.put(writePolicy, key, bins);
// Read written record
Record record = client.get(null, key);
if (record != null) {
System.out.printf("Report: %s %nOccurred: %.0f%n", new Gson().toJson(record.getValue("report")), record.getValue("occurred"));
}
else {
System.out.printf("Record with key: %s does not exist%n", key.userKey.toString());
}
// Update data
Map<String, Object> updateMap = Map.of("zip", Integer.valueOf(98105));
Bin[] updateBins = {
new Bin("occurred", Value.get(5D)), // Increment amount
new Bin("report", Value.get(updateMap)) // Updated report payload
};
// Update operations
Operation[] operations = {
Operation.add(updateBins[0]), // Increment
Operation.put(updateBins[1]), // Replace/update
};
// Update record
client.operate(writePolicy, key, operations);
// Read updated record
Record updateRecord = client.get(null, key);
if (updateRecord != null) {
System.out.printf("Report: %s \nOccurred: %.0f%n", new Gson().toJson(updateRecord.getValue("report")), updateRecord.getValue("occurred"));
}
else {
System.out.printf("UpdateRecord with key: %s does not exist%n", key.userKey.toString());
}
# The following is the primary key of a record
#
# key = (namespace_name, set_name, user_key)
#
# The following is the Aerospike record associated with that key.
#
# bins = {
# 'l': [ "qwertyuiop", 1, bytearray("asd;as[d'as;d", "utf-8") ],
# 'm': { "key": "asd';q;'1';" },
# 'i': 1234,
# 'f': 3.14159265359,
# 's': '!@#@#$QSDAsd;as'
# }
ops = [
operations.increment('i', 1)
operations.read('i')
operations.append('s', 'foobarbaz')
operations.read('s')
]
client.operate(key, ops)
# Expected result:
# i is now 1235
# s is now !@#@#$QSDAsd;asfoobarbaz
Usage notes
All read and write operations on records accept policy parameters: Max Retries and Total Timeout.
Write commands take an optional time to live (TTL) parameter which specifies how long the record can live before Aerospike automatically expires it and removes it from the primary index. For details on the interaction between TTL and eviction, see Managing storage capacity.
A transaction’s constituent operations may accept or require additional policy parameters. For additional details about those parameters, refer to the API reference for the client and operation you are using.
Server responses
Some types of write operations do not return results
by default, which can make it difficult to determine the correct result offset.
To ensure that every write operation returns a result, set the
WritePolicy.respondAllOps
field to true
.
ClientPolicy clientPolicy = new ClientPolicy();
clientPolicy.WritePolicyDefault.respondAllOps = true;
References
See these topics for language-specific examples: