Transactions
CRUD operations
The following example demonstrates create, update, read, and delete (CRUD) operations
within a transaction. For the purposes of this example, the following records
are held in a bin named sightings
:
"sightings": [ {"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]}\""}} {"sighting":{"occurred":20200322,"reported":20200322,"posted":20200515,"report":{"city":"Pismo Beach","duration":"5 minutes","shape":["light"],"state":"CA","summary":"About 20 solid, bright lights moving at the same altitude, heading and speed. Spaced perfectly apart flying over the ocean headed south."},"location":"\"{\"type\":\"Point\",\"coordinates\":[-120.6595,35.1546]}\""}} {"sighting":{"occurred":20200530,"reported":20200531,"posted":20200625,"report":{"city":"New York Staten Island","duration":"2 minutes","shape":["disk"],"state":"NY","summary":"Round shaped object observed over Staten Island NYC, while sitting in my back yard. My daughter also observed this object . Bright White shaped object moving fast from East to West . Observed over Graniteville, Staten Island towards the Elizabeth NJ area and appears to be fast. We then lost view of it due to the clouds."}}}]
Complete example:
import static com.aerospike.client.ResultCode.MRT_VERSION_MISMATCH;
import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;
import com.aerospike.client.AerospikeClient;import com.aerospike.client.AerospikeException;import com.aerospike.client.Bin;import com.aerospike.client.CommitStatus;import com.aerospike.client.Key;import com.aerospike.client.Record;import com.aerospike.client.Txn;import com.aerospike.client.Value;import com.aerospike.client.cdt.CTX;import com.aerospike.client.cdt.ListOperation;import com.aerospike.client.cdt.ListReturnType;import com.aerospike.client.cdt.MapOperation;import com.aerospike.client.cdt.MapOrder;import com.aerospike.client.cdt.MapPolicy;import com.aerospike.client.cdt.MapWriteMode;import com.aerospike.client.policy.RecordExistsAction;import com.aerospike.client.policy.WritePolicy;import com.google.gson.Gson;import com.google.gson.reflect.TypeToken;
public class Transactions { public static void main(String ... args) { AerospikeClient client = new AerospikeClient("127.0.0.1", 3000);
// Aerospike namespace, set, and key_id to be used for the Aerospike key String namespace = "sandbox"; String set = "ufo"; String binName = "sightings"; int keyId = 6120, updateRecordIndex = 0;
// Example JSON string String sightings = "[{\"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]}\\\"\"}},\n"+ "{\"sighting\":{\"occurred\":20200530,\"reported\":20200531,\"posted\":20200625,\"report\":{\"city\":\"New York Staten Island\",\"duration\":\"2 minutes\",\"shape\":[\"disk\"],\"state\":\"NY\",\"summary\":\"Round shaped object observed over Staten Island NYC, while sitting in my back yard. My daughter also observed this object . Bright White shaped object moving fast from East to West . Observed over Graniteville, Staten Island towards the Elizabeth NJ area and appears to be fast. We then lost view of it due to the clouds.\"}}}]";
// Convert string to Java Map List<Map<String, Object>> sightingMap = new Gson().fromJson(sightings, new TypeToken<ArrayList<HashMap<String, Object>>>(){}.getType());
// Start transaction Txn transaction = new Txn();
// Define Aerospike key Key key = new Key(namespace, set, keyId);
// Set bins for "sightings" and "city" Bin sightingsBin = new Bin(binName, Value.get(sightingMap));
// Create write policy WritePolicy writePolicy = client.copyWritePolicyDefault(); writePolicy.recordExistsAction = RecordExistsAction.UPDATE; writePolicy.durableDelete = true; writePolicy.txn = transaction;
System.out.printf("Begin transaction: %d%n", transaction.getId()); Record operationResponse = null; try { operationResponse = performOperationWithTransaction(client, binName, updateRecordIndex, sightingMap, key, sightingsBin, writePolicy); } // Write failed catch (AerospikeException ae) { if (ae.getInDoubt()) { CommitStatus status = null; try { // When in doubt need to attempt to re-commit status = client.commit(transaction); } catch (AerospikeException retryAerospikeException) { if (retryAerospikeException.getInDoubt()) { // If recommit fails and still in doubt, you need to specially handle the records, // possibly log them for later cleanup System.out.printf( "Write failed. %nRecord: %s%n", key.userKey.toLong(), new Gson().toJson(sightingMap) ); } else { if (status == CommitStatus.OK) { // Otherwise retry transaction here operationResponse = performOperationWithTransaction(client, binName, updateRecordIndex, sightingMap, key, sightingsBin, writePolicy); } } } } else { if (ae.getResultCode() == MRT_VERSION_MISMATCH) { // Transaction was invalidated due to a read verification failure. Retry operationResponse = performOperationWithTransaction(client, binName, updateRecordIndex, sightingMap, key, sightingsBin, writePolicy); } else { // Other commit failure - MRT is aborted so normally best course of action is to retry operationResponse = performOperationWithTransaction(client, binName, updateRecordIndex, sightingMap, key, sightingsBin, writePolicy); } } } // Write failed catch (Exception exception) { // Aborting transaction on failure client.abort(transaction); System.out.printf("Write failed %nError: %s%n", exception.getMessage()); }
// Commit transaction client.commit(transaction);
// Extract transaction results from records List<?> response = (List<?>) operationResponse.getValue(binName); // Fetching operation results as list of individual operation result. In this case update, delete, and read
Map<String, Object> removedRecord = (Map<String, Object>) response.get(1); // Fetching delete operation result. In our example we have asked for the removed record to be returned
List<Map<String, Map<String, Map<String, Map<String, Object>>>>> binAfterOperation = (List<Map<String, Map<String, Map<String, Map<String, Object>>>>>) response.get(2); // Fetching read operation results. In our example this would be all the records in `sightings` bin
System.out.printf( "Inserted Objects: %s%n", new Gson().toJson(sightingMap) ); System.out.printf( "Updated `city` with value %s in object %s%n", binAfterOperation.get(0).get("sighting").get("report").get("city"), binAfterOperation.get(0) ); System.out.printf( "Deleted from bin %s record %s%n", binName, new Gson().toJson(removedRecord) );
// Close the client client.close(); }
private static Record performOperationWithTransaction( AerospikeClient client, String binName, int updateRecordIndex, List<Map<String, Object>> sightingMap, Key key, Bin sightingsBin, WritePolicy writePolicy) {
// Writing record to Aerospike client.put(writePolicy, key, sightingsBin); System.out.printf("Created succeeded %nKey: %d%n", key.userKey.toLong());
// Update record Record operationResponse = client.operate(writePolicy, key, MapOperation.put( // Record update first record in the list and assigning value `Seattle` to key `city` new MapPolicy(MapOrder.KEY_VALUE_ORDERED, MapWriteMode.UPDATE), binName, // Bin to be updated Value.get("city"), // Key to be updated Value.get("Seattle"), // Updated value CTX.listIndex(updateRecordIndex), CTX.mapKey(Value.get("sighting")), CTX.mapKey(Value.get("report"))), ListOperation.removeByIndex(binName, 1, ListReturnType.VALUE), // Removing second record in list ListOperation.getRange(binName, 0, sightingMap.size()) // Returning remaining records );
return operationResponse; }}