Last updated: June 22, 2021
This notebook demonstrates Java Aerospike CRUD operations (Create, Read, Update, Delete) for maps of data, focusing on server-side read and update operations.
Aerospike stores records by association with a key. Maps contain key:value pairs. This notebook makes use of the word mapkey to distinguish from a record key.
This Jupyter Notebook requires the Aerospike Database running locally with Java kernel and Aerospike Java Client. To create a Docker container that satisfies the requirements and holds a copy of these notebooks, visit the Aerospike Notebooks Repo.
Run these first to initialize Jupyter, download the Java Client, and make sure the Aerospike Database is running.
Make it easier to work with Java in Jupyter.
import io.github.spencerpark.ijava.IJava;
import io.github.spencerpark.jupyter.kernel.magic.common.Shell;
IJava.getKernelInstance().getMagics().registerMagics(Shell.class);
Ensure Aerospike Database is running locally.
%sh asd
Ask Maven to download and install the project object model (POM) of the Aerospike Java Client.
%%loadFromPOM
<dependencies>
<dependency>
<groupId>com.aerospike</groupId>
<artifactId>aerospike-client</artifactId>
<version>5.0.0</version>
</dependency>
</dependencies>
Create an instance of the Aerospike Java Client, and connect to the demo cluster.
The default cluster location for the Docker container is localhost port 3000. If your cluster is not running on your local machine, modify localhost and 3000 to the values for your Aerospike cluster.
import com.aerospike.client.AerospikeClient;
AerospikeClient client = new AerospikeClient("localhost", 3000);
System.out.println("Initialized the client and connected to the cluster.");
Initialized the client and connected to the cluster.
Create a string map representing fish metadata. Create an integer map containing timestamped fish observation locations.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
HashMap <String, String> mapFish = new HashMap <String, String>();
mapFish.put("name", "Annette");
mapFish.put("fruit", "Pineapple");
mapFish.put("color", "Aquamarine");
mapFish.put("tree", "Redwood");
System.out.println("Fish Map: " + mapFish);
HashMap <Integer, HashMap> mapObs = new HashMap <Integer, HashMap>();
HashMap <String, Integer> mapCoords0 = new HashMap <String, Integer>();
mapCoords0.put("lat", -85);
mapCoords0.put("long", -130);
HashMap <String, Integer> mapCoords1 = new HashMap <String, Integer>();
mapCoords1.put("lat", -25);
mapCoords1.put("long", -50);
HashMap <String, Integer> mapCoords2 = new HashMap <String, Integer>();
mapCoords2.put("lat", 35);
mapCoords2.put("long", 30);
mapObs.put(13456, mapCoords1);
mapObs.put(14567, mapCoords2);
mapObs.put(12345, mapCoords0);
System.out.println("Observations Map:" + mapObs);
Fish Map: {color=Aquamarine, fruit=Pineapple, name=Annette, tree=Redwood} Observations Map:{13456={lat=-25, long=-50}, 14567={lat=35, long=30}, 12345={lat=-85, long=-130}}
Insert one record in Aerospike with Key "koi", and Bin Names mapfishbin and mapobsbin.
By default, Aerospike data is unsorted, however Aerospike preserves order by index when inserting data. Java HashMaps are sorted by mapkey by default.
A Key uniquely identifies a specific record in your Aerospike server or cluster. Each key must have a Namespace and optionally a Set name.
The namespace test is configured on your Aerospike server or cluster.
For additional information on the Aerospike Data Model, go here.
import com.aerospike.client.Key;
String mapSet = "mapset1";
String mapNamespace = "test";
String theKey = "koi";
Key key = new Key(mapNamespace, mapSet, theKey);
System.out.println("Key created." );
Key created.
A Bin is a data field in an Aerospike record.
import com.aerospike.client.Bin;
String mapFishBinName = "mapfishbin";
String mapObsBinName = "mapobsbin";
Bin bin1 = new Bin(mapFishBinName, mapFish);
Bin bin2 = new Bin(mapObsBinName, mapObs);
System.out.println( "Created " + bin1 + " and " + bin2 + ".");
Created mapfishbin:{color=Aquamarine, fruit=Pineapple, name=Annette, tree=Redwood} and mapobsbin:{13456={lat=-25, long=-50}, 14567={lat=35, long=30}, 12345={lat=-85, long=-130}}.
import com.aerospike.client.policy.ClientPolicy;
ClientPolicy clientPolicy = new ClientPolicy();
System.out.println("Created a client policy.");
Created a client policy.
client.put(clientPolicy.writePolicyDefault, key, bin1, bin2);
System.out.println("Key: " + theKey + "\n" + mapFishBinName + ": " + mapFish + "\n" +
mapObsBinName + ": " + mapObs );
Key: koi mapfishbin: {color=Aquamarine, fruit=Pineapple, name=Annette, tree=Redwood} mapobsbin: {13456={lat=-25, long=-50}, 14567={lat=35, long=30}, 12345={lat=-85, long=-130}}
Now that the maps are in Aerospike, the client can return full or partial maps from bin contents. No data is modified by these ops.
A record can be retrieved using the key, namespace, and set name.
In the output:
For more information on both generation number and expiration, see the Aerospike FAQ.
import com.aerospike.client.Record;
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
System.out.println(record);
(gen:1),(exp:359404034),(bins:(mapfishbin:{name=Annette, tree=Redwood, color=Aquamarine, fruit=Pineapple}),(mapobsbin:{13456={lat=-25, long=-50}, 12345={lat=-85, long=-130}, 14567={lat=35, long=30}}))
import com.aerospike.client.Operation;
import com.aerospike.client.Value;
import com.aerospike.client.cdt.MapOperation;
import com.aerospike.client.cdt.MapReturnType;
String mapKeyToFind = "color";
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
Record colorString = client.operate(null, key,
MapOperation.getByKey(mapFishBinName, Value.get(mapKeyToFind), MapReturnType.VALUE)
);
System.out.println("The string map: " + record.getValue(mapFishBinName));
System.out.println("The " + mapKeyToFind + " in the string map is: " + colorString.getValue(mapFishBinName));
The string map: {name=Annette, tree=Redwood, color=Aquamarine, fruit=Pineapple} The color in the string map is: Aquamarine
Integer highestRank = -1;
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
Record highestRankString = client.operate(null, key,
MapOperation.getByRank(mapFishBinName, highestRank, MapReturnType.VALUE)
);
System.out.println("The string map: " + record.getValue(mapFishBinName));
System.out.println("The highest rank string is: " + highestRankString.getValue(mapFishBinName));
The string map: {name=Annette, tree=Redwood, color=Aquamarine, fruit=Pineapple} The highest rank string is: Redwood
Aerospike provides operations to look up an element by value and return the mapkey.
String valueToFind = "Pineapple";
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
Record foundMapKey = client.operate(null, key,
MapOperation.getByValue(mapFishBinName, Value.get(valueToFind), MapReturnType.KEY)
);
System.out.println("The string map: " + record.getValue(mapFishBinName));
System.out.println("The mapkey associated with " + valueToFind + " is: " + foundMapKey.getValue(mapFishBinName));
The string map: {name=Annette, tree=Redwood, color=Aquamarine, fruit=Pineapple} The mapkey associated with Pineapple is: [fruit]
Aerospike operations can read integers associated with fish observations.
The mapobsbin is a list of Latitude/Longitude pairs stored by the time of fish observation in seconds from the start of the experiment. The number of seconds, latitude, and longitude are all integers.
Aerospike API's size operation returns a count of the mapkeys in a map.
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
Record sizeString = client.operate(null, key,
MapOperation.size(mapObsBinName)
);
System.out.println("The Observation Map: " + record.getValue(mapObsBinName));
System.out.println("The number of Observations in the Map: "
+ sizeString.getValue(mapObsBinName));
The Observation Map: {13456={lat=-25, long=-50}, 12345={lat=-85, long=-130}, 14567={lat=35, long=30}} The number of Observations in the Map: 3
Aerospike API operations can look up a value by index. In Aerospike, the index operation can get one or more map elements by key order. Aerospike allows indexing forward from the beginning of the map using zero-based numbering. Negative numbers index backwards from the end of a map.
In this example, the first element by index represents the first time the fish was observed. Because the key 12345 is before 13456 and 14567, the first element by index is 12345.
For examples of indexes, go here.
Integer firstIdx = 0;
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
Record firstObservation = client.operate(null, key,
MapOperation.getByIndex(mapObsBinName, firstIdx, MapReturnType.KEY_VALUE)
);
System.out.println("The Observation Map: " + record.getValue(mapObsBinName));
System.out.println("The First Observation: " + firstObservation.getValue(mapObsBinName));
The Observation Map: {13456={lat=-25, long=-50}, 12345={lat=-85, long=-130}, 14567={lat=35, long=30}} The First Observation: [12345={lat=-85, long=-130}]
Aerospike delivers values by mapkey range. Get the latitude and longitude pairs for all observations between 13,000 and 15,000 seconds.
Integer lowerBound = 13000;
Integer upperBound = 15000;
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
Record rangeObservations = client.operate(null, key,
MapOperation.getByKeyRange(mapObsBinName, Value.get(lowerBound), Value.get(upperBound),
MapReturnType.KEY_VALUE)
);
System.out.println("The Observation Map: " + record.getValue(mapObsBinName));
System.out.println("The Observations between 13000 and 15000 seconds: "
+ rangeObservations.getValue(mapObsBinName));
The Observation Map: {13456={lat=-25, long=-50}, 12345={lat=-85, long=-130}, 14567={lat=35, long=30}} The Observations between 13000 and 15000 seconds: [13456={lat=-25, long=-50}, 14567={lat=35, long=30}]
Aerospike's MapOperations can also modify data in the Aerospike Database.
The Fish Bin contains metadata about the fish.
import com.aerospike.client.cdt.MapPolicy;
MapPolicy mapFishBinPolicy = new MapPolicy();
System.out.println("Created default MapPolicy for " + mapFishBinName + ".")
Created default MapPolicy for mapfishbin.
When new data is put into a map, Aerospike returns the size of the resulting map.
String treeMapkeyName = "tree";
String newTree = "Larch";
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
Record sizeOfMapWithNewTree = client.operate(null, key,
MapOperation.put(mapFishBinPolicy, mapFishBinName, Value.get(treeMapkeyName),
Value.get(newTree))
);
Record mapWithNewTree = client.get(null, key);
System.out.println("Before: " + record.getValue(mapFishBinName));
System.out.println("The size after the operation: "
+ sizeOfMapWithNewTree.getValue(mapFishBinName));
System.out.println(" After: " + mapWithNewTree.getValue(mapFishBinName));
Before: {name=Annette, tree=Redwood, color=Aquamarine, fruit=Pineapple} The size after the operation: 4 After: {name=Annette, tree=Larch, color=Aquamarine, fruit=Pineapple}
When removing a mapkey:value pair, Aerospike client returns the removed data.
String fruitMapkeyName = "fruit";
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
Record valOfRemovedFruit = client.operate(null, key,
MapOperation.removeByKey(mapFishBinName, Value.get(fruitMapkeyName),
MapReturnType.KEY_VALUE)
);
Record mapWithoutFruit = client.get(null, key);
System.out.println("Before: " + record.getValue(mapFishBinName));
System.out.println("The removed mapkey/value pair: "
+ valOfRemovedFruit.getValue(mapFishBinName));
System.out.println("After removing the " + fruitMapkeyName + ": "
+ mapWithoutFruit.getValue(mapFishBinName));
Before: {name=Annette, tree=Larch, color=Aquamarine, fruit=Pineapple} The removed mapkey/value pair: [fruit=Pineapple] After removing the fruit: {color=Aquamarine, name=Annette, tree=Larch}
To be sure that other scientists can catch the fish, add the fish's preferred bait to the record.
String mapkeyForBait = "bait";
String valueForBait = "Mosquito Larva";
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
Record sizeOfRecordWithBait = client.operate(null, key,
MapOperation.put(mapFishBinPolicy, mapFishBinName, Value.get(mapkeyForBait),
Value.get(valueForBait))
);
Record recordWithBait = client.get(null, key);
System.out.println("Before: " + record.getValue(mapFishBinName));
System.out.println("After adding Bait: " + recordWithBait.getValue(mapFishBinName));
Before: {color=Aquamarine, name=Annette, tree=Larch} After adding Bait: {name=Annette, tree=Larch, color=Aquamarine, bait=Mosquito Larva}
The experiment continued past the original end date. The new work requires keeping track of the total number of observations.
String mapkeyObsCount = "Count";
Integer numObservations = 3;
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
Record sizeOfRecordWithObsCounter =
client.operate(null, key, MapOperation.put(mapFishBinPolicy, mapFishBinName,
Value.get(mapkeyObsCount),
Value.get(numObservations))
);
Record recordWithObsCount = client.get(null, key);
System.out.println("Before: " + record.getValue(mapFishBinName));
System.out.println("After Adding the Counter: " + recordWithObsCount.getValue(mapFishBinName));
Before: {name=Annette, tree=Larch, color=Aquamarine, bait=Mosquito Larva} After Adding the Counter: {name=Annette, tree=Larch, Count=3, color=Aquamarine, bait=Mosquito Larva}
Aerospike client can update map elements, such as integers and sub-maps.
The experiment continued past the original end date. The new work requires the regular addition of new observations and keeping track of the total number of observations.
In this example, the Observations Map should be maintained as mapkey-sorted in Aerospike, but are put unordered into the database by default. When storing any map on SSD hardware, Key Ordered Maps hold a significant performance advantage over Unordered Maps, at a cost of 4 bytes of storage for metadata.
The MapPolicy contains two types of configurations, MapOrder and MapWriteFlags. The maporder determines the sort order of the map. The mapwriteflags determine write behaviors, such as if the operation should fail when a mapkey/value already exists.
For more information on maporder, go here.
For more information on mapwriteflags, go here.
import com.aerospike.client.cdt.MapOrder;
import com.aerospike.client.cdt.MapWriteFlags;
Record recordObsUnordered = client.get(null, key);
MapPolicy mapObsBinPolicy = new MapPolicy(MapOrder.KEY_ORDERED, MapWriteFlags.DEFAULT);
Record changeOrder =
client.operate(null, key, MapOperation.setMapPolicy(mapObsBinPolicy, mapObsBinName));
Record recordObsOrdered = client.get(null, key);
System.out.println("Before Sorting: " + recordObsUnordered.getValue(mapObsBinName));
System.out.println("Applied mapkey-ordered MapPolicy for " + mapObsBinName + ".");
System.out.println("After Sorting: " + recordObsOrdered.getValue(mapObsBinName));
Before Sorting: {13456={lat=-25, long=-50}, 12345={lat=-85, long=-130}, 14567={lat=35, long=30}} Applied mapkey-ordered MapPolicy for mapobsbin. After Sorting: {12345={lat=-85, long=-130}, 13456={lat=-25, long=-50}, 14567={lat=35, long=30}}
int newObsTimestamp = 15678;
int newObsLat = 80;
int newObsLong = 110;
HashMap <Integer, HashMap> mapNewObs = new HashMap <Integer, HashMap>();
HashMap <String, Integer> mapNewCoords = new HashMap <String, Integer>();
mapNewCoords.put("lat", newObsLat);
mapNewCoords.put("long", newObsLong);
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
Record sizeOfNewObs = client.operate(null, key,
MapOperation.put(mapObsBinPolicy, mapObsBinName, Value.get(newObsTimestamp), Value.get(mapNewCoords))
);
Record recordWithNewObs = client.get(null, key);
System.out.println("Before: " + record.getValue(mapObsBinName));
System.out.println("The Size After Adding the Observation: " + sizeOfNewObs.getValue(mapObsBinName));
System.out.println("After Adding the Observation: " + recordWithNewObs.getValue(mapObsBinName));
Before: {12345={lat=-85, long=-130}, 13456={lat=-25, long=-50}, 14567={lat=35, long=30}} The Size After Adding the Observation: 4 After Adding the Observation: {12345={lat=-85, long=-130}, 13456={lat=-25, long=-50}, 14567={lat=35, long=30}, 15678={lat=80, long=110}}
This study only maintains the three most recent observations.
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
Record oldObs = client.operate(null, key,
MapOperation.removeByIndex(mapObsBinName, firstIdx, MapReturnType.KEY_VALUE)
);
Record updatedRecord = client.get(null, key);
System.out.println("Before: " + record.getValue(mapObsBinName));
System.out.println("The Removed Observation: " + oldObs.getValue(mapObsBinName));
System.out.println("After Observation Removal: " + updatedRecord.getValue(mapObsBinName));
Before: {12345={lat=-85, long=-130}, 13456={lat=-25, long=-50}, 14567={lat=35, long=30}, 15678={lat=80, long=110}} The Removed Observation: [12345={lat=-85, long=-130}] After Observation Removal: {13456={lat=-25, long=-50}, 14567={lat=35, long=30}, 15678={lat=80, long=110}}
When incrementing a map value, Aerospike returns the new value.
int incNum = 1;
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
Record obsCount = client.operate(null, key,
MapOperation.increment(mapFishBinPolicy, mapFishBinName, Value.get(mapkeyObsCount), Value.get(incNum))
);
Record updatedRecord = client.get(null, key);
System.out.println("Before: " + record.getValue(mapFishBinName));
System.out.println("The New Count: " + obsCount.getValue(mapFishBinName));
System.out.println("After Increment: " + updatedRecord.getValue(mapFishBinName));
Before: {name=Annette, tree=Larch, Count=3, color=Aquamarine, bait=Mosquito Larva} The New Count: 4 After Increment: {name=Annette, tree=Larch, Count=4, color=Aquamarine, bait=Mosquito Larva}
Truncate the set from the Aerospike Database.
import com.aerospike.client.policy.InfoPolicy;
InfoPolicy infoPolicy = new InfoPolicy();
client.truncate(infoPolicy, mapNamespace, mapSet, null);
System.out.println("Set Truncated.");
Set Truncated.
client.close();
System.out.println("Server connection(s) closed.");
Server connection(s) closed.
Here is a collection of all of the non-Jupyter code from this tutorial.
// Import Java Libraries.
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
// Import Aerospike Client Libraries.
import com.aerospike.client.AerospikeClient;
import com.aerospike.client.Key;
import com.aerospike.client.Bin;
import com.aerospike.client.policy.ClientPolicy;
import com.aerospike.client.Record;
import com.aerospike.client.Operation;
import com.aerospike.client.Value;
import com.aerospike.client.cdt.MapOperation;
import com.aerospike.client.cdt.MapReturnType;
import com.aerospike.client.cdt.MapPolicy;
import com.aerospike.client.cdt.MapOrder;
import com.aerospike.client.cdt.MapWriteFlags;
import com.aerospike.client.policy.InfoPolicy;
// Start the Aerospike Client.
AerospikeClient client = new AerospikeClient("localhost", 3000);
System.out.println("Initialized the client and connected to the cluster.");
// Create Test Data.
HashMap <String, String> mapFish = new HashMap <String, String>();
mapFish.put("name", "Annette");
mapFish.put("fruit", "Pineapple");
mapFish.put("color", "Aquamarine");
mapFish.put("tree", "Redwood");
System.out.println("Created Fish Map: " + mapFish);
HashMap <Integer, HashMap> mapObs = new HashMap <Integer, HashMap>();
HashMap <String, Integer> mapCoords0 = new HashMap <String, Integer>();
mapCoords0.put("lat", -85);
mapCoords0.put("long", -130);
HashMap <String, Integer> mapCoords1 = new HashMap <String, Integer>();
mapCoords1.put("lat", -25);
mapCoords1.put("long", -50);
HashMap <String, Integer> mapCoords2 = new HashMap <String, Integer>();
mapCoords2.put("lat", 35);
mapCoords2.put("long", 30);
mapObs.put(13456, mapCoords1);
mapObs.put(14567, mapCoords2);
mapObs.put(12345, mapCoords0);
System.out.println("Created Observations Map: " + mapObs);
// Put Record into Aerospike.
String mapSet = "mapset1";
String mapNamespace = "test";
String theKey = "koi";
String mapFishBin = "mapfishbin";
String mapObsBin = "mapobsbin";
ClientPolicy clientPolicy = new ClientPolicy();
InfoPolicy infoPolicy = new InfoPolicy();
Key key = new Key(mapNamespace, mapSet, theKey);
Bin bin1 = new Bin(mapFishBin, mapFish);
Bin bin2 = new Bin(mapObsBin, mapObs);
client.put(clientPolicy.writePolicyDefault, key, bin1, bin2);
System.out.println("Inserted Key: " + theKey + "\n " + mapFishBin + ": " + mapFish + "\n " +
mapObsBin + ": " + mapObs );
System.out.println();
// Get Data from Aerospike.
// 1. Get the Record.
// 2. Get String by MapKey and Highest Rank.
// 3. Get MapKey by String.
// 3. Get the Number of Observations and 1st Observation By Index.
// 4. Get Observations by MapKey Range.
String mapKeyToFind = "color";
Integer highestRank = -1;
String valueToFind = "Pineapple";
Integer firstIdx = 0;
Integer lowerBound = 13000;
Integer upperBound = 15000;
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
Record results = client.operate(null, key,
MapOperation.getByKey(mapFishBin, Value.get(mapKeyToFind), MapReturnType.VALUE),
MapOperation.getByRank(mapFishBin, highestRank, MapReturnType.VALUE),
MapOperation.getByValue(mapFishBin, Value.get(valueToFind), MapReturnType.KEY),
MapOperation.size(mapObsBin),
MapOperation.getByIndex(mapObsBin, firstIdx, MapReturnType.KEY_VALUE),
MapOperation.getByKeyRange(mapObsBin, Value.get(lowerBound), Value.get(upperBound), MapReturnType.KEY_VALUE)
);
List<?> resultsFish = results.getList(mapFishBin);
List<?> resultsObs = results.getList(mapObsBin);
System.out.println("Read the Full Record From Aerospike:" + record);
System.out.println("The " + mapKeyToFind + " in the string map is: " + resultsFish.get(0));
System.out.println("The highest rank string is: " + resultsFish.get(1));
System.out.println("The mapkey associated with " + valueToFind + " is: " + resultsFish.get(2));
System.out.println("The number of Observations in the Map: " + resultsObs.get(0));
System.out.println("The First Observation: " + resultsObs.get(1));
System.out.println("The Observations between 13000 and 15000 seconds: " + resultsObs.get(2));
System.out.println();
// 7. Update the Record in Aerospike
// 1. Change the Tree to a Larch
// 2. Remove the Fruit and add Bait.
// 3. Add an Observation Counter.
// 4. Sort the Observation Map.
// 5. Add a New Observation.
// 6. Remove the Oldest Operation.
// 7. Increment the Observation Counter.
MapPolicy mapFishBinPolicy = new MapPolicy();
MapPolicy mapObsBinPolicy = new MapPolicy(MapOrder.KEY_ORDERED, MapWriteFlags.DEFAULT);
String treeMapkeyName = "tree";
String newTree = "Larch";
String fruitMapkeyName = "fruit";
String mapkeyForBait = "bait";
String valueForBait = "Mosquito Larva";
String mapkeyObsCount = "Count";
Integer numObservations = 3;
int newObsTimestamp = 15678;
int newObsLat = 80;
int newObsLong = 110;
int incNum = 1;
HashMap <Integer, HashMap> mapNewObs = new HashMap <Integer, HashMap>();
HashMap <String, Integer> mapNewCoords = new HashMap <String, Integer>();
mapNewCoords.put("lat", newObsLat);
mapNewCoords.put("long", newObsLong);
Key key = new Key(mapNamespace, mapSet, theKey);
Record record = client.get(null, key);
Record updatingRecord = client.operate(null, key,
MapOperation.put(mapFishBinPolicy, mapFishBin, Value.get(treeMapkeyName),
Value.get(newTree)),
MapOperation.removeByKey(mapFishBin, Value.get(fruitMapkeyName),
MapReturnType.KEY_VALUE),
MapOperation.put(mapFishBinPolicy, mapFishBin, Value.get(mapkeyForBait),
Value.get(valueForBait)),
MapOperation.put(mapFishBinPolicy, mapFishBin, Value.get(mapkeyObsCount),
Value.get(numObservations)),
MapOperation.setMapPolicy(mapObsBinPolicy, mapObsBin),
MapOperation.put(mapObsBinPolicy, mapObsBin, Value.get(newObsTimestamp),
Value.get(mapNewCoords)),
MapOperation.removeByIndex(mapObsBin, firstIdx, MapReturnType.KEY_VALUE),
MapOperation.increment(mapFishBinPolicy, mapFishBin, Value.get(mapkeyObsCount),
Value.get(incNum))
);
Record finalRecord = client.get(null, key);
List<?> updateFish = updatingRecord.getList(mapFishBin);
List<?> updateObs = updatingRecord.getList(mapObsBin);
System.out.println("Changed " + treeMapkeyName + " to " + newTree + "; there are now " + updateFish.get(0) + " map items in " + mapFishBin);
System.out.println("Removed item " + updateFish.get(1));
System.out.println("Added item [" + mapkeyForBait + "=" + valueForBait + "]; there are now " + updateFish.get(2) + " map items in " + mapFishBin);
System.out.println("Added Observation Counter; there are now " + updateFish.get(3) + " map items in " + mapFishBin);
System.out.println("Sorted " + mapObsBin);
System.out.println("Added New Observation {" + newObsTimestamp + "=" + mapNewCoords + "}, there are now " + updateObs.get(1) + " map items in " + mapObsBin);
System.out.println("Removed Oldest Observation: " + updateObs.get(2));
System.out.println("Incremented Observation Counter to reflect " + updateFish.get(4) + "th observation");
System.out.println();
System.out.println("After Record Edits: " + finalRecord);
// Truncate the Set.
client.truncate(infoPolicy, mapNamespace, mapSet, null);
System.out.println("Set Truncated.");
// Close the Client Connections.
client.close();
Initialized the client and connected to the cluster. Created Fish Map: {color=Aquamarine, fruit=Pineapple, name=Annette, tree=Redwood} Created Observations Map: {13456={lat=-25, long=-50}, 14567={lat=35, long=30}, 12345={lat=-85, long=-130}} Inserted Key: koi mapfishbin: {color=Aquamarine, fruit=Pineapple, name=Annette, tree=Redwood} mapobsbin: {13456={lat=-25, long=-50}, 14567={lat=35, long=30}, 12345={lat=-85, long=-130}} Read the Full Record From Aerospike:(gen:1),(exp:359404037),(bins:(mapfishbin:{name=Annette, tree=Redwood, color=Aquamarine, fruit=Pineapple}),(mapobsbin:{13456={lat=-25, long=-50}, 12345={lat=-85, long=-130}, 14567={lat=35, long=30}})) The color in the string map is: Aquamarine The highest rank string is: Redwood The mapkey associated with Pineapple is: [fruit] The number of Observations in the Map: 3 The First Observation: [12345={lat=-85, long=-130}] The Observations between 13000 and 15000 seconds: [13456={lat=-25, long=-50}, 14567={lat=35, long=30}] Changed tree to Larch; there are now 4 map items in mapfishbin Removed item [fruit=Pineapple] Added item [bait=Mosquito Larva]; there are now 4 map items in mapfishbin Added Observation Counter; there are now 5 map items in mapfishbin Sorted mapobsbin Added New Observation {15678={lat=80, long=110}}, there are now 4 map items in mapobsbin Removed Oldest Observation: [12345={lat=-85, long=-130}] Incremented Observation Counter to reflect 4th observation After Record Edits: (gen:2),(exp:359404038),(bins:(mapfishbin:{name=Annette, tree=Larch, Count=4, color=Aquamarine, bait=Mosquito Larva}),(mapobsbin:{13456={lat=-25, long=-50}, 14567={lat=35, long=30}, 15678={lat=80, long=110}})) Set Truncated.
Aerospike and its Java Client are up to the task of working with your map data. Its API provides rich operations to read and update list data using index, mapkey, value, and rank. Not modeled in this tutorial, Aerospike map operation also supports nested lists and maps, by assigning CTX or contexts to operations.
For more information on contexts, go here. For examples of contexts, go here.
Have questions? Don't hesitate to reach out if you have additional questions about working with lists at https://discuss.aerospike.com/.
Want to check out other Java notebooks?
Are you running this from Binder? Download the Aerospike Notebook Repo and work with Aerospike Database and Jupyter locally using a Docker container.