Skip to content

List operations

For the complete documentation index see: llms.txt

All documentation pages available in markdown.

A list bin stores an ordered collection of values. Aerospike’s list CDT (complex data type) operations let the server add, read, and remove individual list elements in a single round trip, without the client reading the whole bin first.

This matters because Client::put always replaces the full bin value. Calling put() a second time with a new Vec<Value> does not append to the existing list. It overwrites it. To add items to a list bin that may already exist, without a read-modify-write round trip, use the aerospike::operations::lists builders with Client::operate().

Setup

use aerospike::operations::lists;
use aerospike::{as_key, Client, ClientPolicy, ListPolicy, ListReturnType, Value, WritePolicy};
let client = Client::new(&ClientPolicy::default(), &"127.0.0.1:3000").await?;
let key = as_key!("test", "carts", "cart:1");
let policy = ListPolicy::default();

📖 API reference: Client::new | operations::lists | ListPolicy

Append to a list bin

lists::append appends a single value to a list bin and creates the bin (and an empty list) if it doesn’t exist yet. No read is required first. Call it again later and it appends again, rather than overwriting:

let ops = vec![lists::append(&policy, "items", Value::from("apple"))];
client.operate(&WritePolicy::default(), &key, &ops).await?;
// Later, in a separate call. This appends "banana", it does not replace "apple".
let ops = vec![lists::append(&policy, "items", Value::from("banana"))];
client.operate(&WritePolicy::default(), &key, &ops).await?;
// items is now ["apple", "banana"]

📖 API reference: operations::lists::append | Client::operate

To append more than one value in a single call, use append_items:

let ops = vec![lists::append_items(
&policy,
"items",
vec![Value::from("cherry"), Value::from("date")],
)];
client.operate(&WritePolicy::default(), &key, &ops).await?;

📖 API reference: operations::lists::append_items

Read the list size

lists::size returns the number of elements in a list bin. Combine it with an append in the same operate() call to append and confirm the new length in one round trip:

let ops = vec![
lists::append(&policy, "items", Value::from("apple")),
lists::size("items"),
];
let record = client.operate(&WritePolicy::default(), &key, &ops).await?;
// record.results holds one answer per operation, in order; the size is the second.
let results = record.results.unwrap();
println!("list size: {:?}", results[1]);

📖 API reference: operations::lists::size | Record::results

Read elements back

lists::get and lists::get_range read one element or a range of elements without removing them:

let ops = vec![lists::get_range("items", 0, 2)]; // first two elements
let record = client.operate(&WritePolicy::default(), &key, &ops).await?;
println!("{:?}", record.results.unwrap()[0]);

📖 API reference: operations::lists::get | operations::lists::get_range

Remove elements

lists::pop removes and returns the element at an index. lists::remove_by_value removes every occurrence of a value and takes a ListReturnType that selects what the server reports about the removed items:

let ops = vec![lists::pop("items", 0)]; // remove and return the first element
client.operate(&WritePolicy::default(), &key, &ops).await?;
// Remove every "banana"; COUNT asks the server to return how many were removed.
let ops = vec![lists::remove_by_value("items", Value::from("banana"), ListReturnType::COUNT)];
client.operate(&WritePolicy::default(), &key, &ops).await?;

📖 API reference: operations::lists::pop | operations::lists::remove_by_value | ListReturnType

For map-bin equivalents (operations::maps) and nested-path navigation with CdtContext, see the operations::maps API reference.