Skip to content

Map operations

For the complete documentation index see: llms.txt

All documentation pages available in markdown.

A map bin stores key-value pairs. Keys are strings, integers, or byte arrays, and values can be any supported data type. The server’s map collection data type (CDT) operations change, read, and remove individual entries in a single round trip, without the client reading the whole bin first.

Client::put always replaces the full bin value. To change entries of a map bin that already exists, use the aerospike::operations::maps builders with Client::operate().

Setup

use aerospike::operations::maps;
use aerospike::{
as_bin, as_key, as_map, as_val, Bins, Client, ClientPolicy, MapPolicy, MapReturnType,
ReadPolicy, Value, WritePolicy,
};
let client = Client::new(&ClientPolicy::default(), &"127.0.0.1:3000").await?;
let policy = MapPolicy::default();

📖 API reference: Client::new | operations::maps | MapPolicy

The as_map! and as_list! macros expand to as_val!, so import as_val too.

Write a map bin

To write a map as the whole value of a bin, build it with as_map! and pass it to put():

let key = as_key!("test", "stats", "page:1");
let bin = as_bin!("daily", as_map!("2026-10-01" => 5));
client.put(&WritePolicy::default(), &key, &[bin]).await?;

📖 API reference: as_map! | Value::HashMap

Increment counters in a map

maps::increment_value(&policy, bin, key, amount) adds amount to the number stored under key. If the key doesn’t exist yet, the server creates it and sets it to amount. No read is required first.

Pass several increments in one operate() call to change several keys in a single round trip. record.results holds one answer per operation, in order. Each answer is the key’s new value:

let key = as_key!("test", "stats", "page:1");
let ops = vec![
maps::increment_value(&policy, "daily", Value::from("2026-10-01"), Value::from(1)),
maps::increment_value(&policy, "daily", Value::from("2026-10-02"), Value::from(1)),
];
let record = client.operate(&WritePolicy::default(), &key, &ops).await?;
println!("{:?}", record.results);

📖 API reference: operations::maps::increment_value | Client::operate

Read a map back

A get returns a map bin as a Value::OrderedMap, which holds the entries in key order. Match on it to read the entries. Key-ordered maps (K-ordered on the server) arrive as Value::SortedMap instead:

let record = client.get(&ReadPolicy::default(), &key, Bins::All).await?;
if let Some(Value::OrderedMap(daily)) = record.bins.get("daily") {
for (date, views) in daily {
println!("{date}: {views}");
}
}

📖 API reference: Value::OrderedMap

Select entries by rank

The rank of an entry is its position when the server sorts the entries by value. Rank 0 is the entry with the lowest value. A negative rank counts from the highest value, so -1 is the highest.

maps::get_by_rank_range(bin, rank, count, return_type) selects count entries that start at rank. To read the three highest-scoring players of a leaderboard, start at rank -3:

let key = as_key!("test", "games", "board:1");
let scores = as_map!("ann" => 120, "bob" => 340, "cat" => 90, "dan" => 500, "eve" => 275);
client.put(&WritePolicy::default(), &key, &[as_bin!("scores", scores)]).await?;
let ops = vec![maps::get_by_rank_range("scores", -3, 3, MapReturnType::KeyValue)];
let record = client.operate(&WritePolicy::default(), &key, &ops).await?;
// The entries come back from the lowest of the three scores to the highest.
if let Some(Value::KeyValueList(entries)) = record.operation_result(0) {
for (player, score) in entries.iter().rev() {
println!("{player}: {score}");
}
}

📖 API reference: operations::maps::get_by_rank_range | Value::KeyValueList

MapReturnType::KeyValue returns the selected entries as a Value::KeyValueList, a list of (key, value) pairs in rank order. The server selects the entries, so the program doesn’t fetch and sort the whole map.

Remove a key and return its value

maps::remove_by_key(bin, key, return_type) removes one entry from the map. The return type selects what the server sends back about the removed entry. To remove a key and get its value in the same call, use MapReturnType::Value:

let key = as_key!("test", "settings", "user:1");
let prefs = as_map!("lang" => "en", "theme" => "dark", "beta" => true);
client.put(&WritePolicy::default(), &key, &[as_bin!("prefs", prefs)]).await?;
let ops = vec![maps::remove_by_key("prefs", Value::from("beta"), MapReturnType::Value)];
let record = client.operate(&WritePolicy::default(), &key, &ops).await?;
println!("removed: {:?}", record.operation_result(0));

📖 API reference: operations::maps::remove_by_key

The other entries of the map stay as they were. The server updates the entry in place, and the client sends one map operation instead of reading and writing the whole bin.

Choose what an operation returns

Map read and remove operations take a MapReturnType that selects what the server returns for the entries the operation selected:

MapReturnTypeWhat the server returns
NoneNothing. The result is Value::Nil.
CountThe number of entries selected.
KeyThe key of a single entry, or a list of keys for a range.
ValueThe value of a single entry, or a list of values for a range.
KeyValueThe entries as key-value pairs.
IndexThe key-order position of the entry, where 0 is the first key.
ReverseIndexThe position in reverse key order, where 0 is the last key.
RankThe rank of the entry, where 0 is the lowest value.
ReverseRankThe rank in reverse value order, where 0 is the highest value.
Existstrue if the operation selected at least one entry.

📖 API reference: MapReturnType

To invert a selection, pass InvertedMapReturn(MapReturnType::Key) from aerospike::operations::maps instead of the plain return type.

For nested-path navigation with CdtContext, see the operations::maps API reference.

Next steps