Create
The Aerospike Rust clientβs put() method writes records to the database.
Note that if they do not already exist, the set and bins are automatically created.
You donβt have to define a schema for the database.
The following examples adds a bin mybin in the record mykey with a string value
myvalue. This example uses the namespace test, which is the default
namespace specified in the server configuration file.
The following write policy specifies the re-transmission policy,
timeout interval, record expiration, and what to do if the record already exists.
The examples demonstrate v2.0 of the client. v1.3 uses a slightly different interface, but is very similar.
let policy = WritePolicy::default();policy.base().total_timeout = 50; // 50 millisecond timeout.π API Reference:
WritePolicy::default
Writing single value
When writing records, you must identify the record in the database using a key.
The following example creates a key for the record to insert. The value used
for the key is the string mykey, to be stored in the Namespace test in
the set myset. You can use other data types, such as integer for key.
let key = as_key!("test", "myset", "mykey");let bin = as_bin!("mybin", "myvalue");match client.put(&policy, &key, &vec![&bin]).await { Ok(()) => println!("Record written"), Err(err) => println!("Error writing record: {}", err),}π API Reference:
Client::put
Observe that we pass the bin inside a vector, even if there is only one.
Writing multiple values
To update multiple bins in a record, create additional bins and add them to the put() call:
// Write multiple values.let bin1 = as_bin!("name", "John");let bin2 = as_bin!("age", 25);match client.put(&policy, &key, &vec![&bin1, &bin2]).await { Ok(()) => println!("All records written"), Err(err) => println!("Error writing records: {}", err),};π API Reference:
Client::put
Deleting a bin
To delete a bin, set the bin value to the empty value:
// Delete the "age" bin by writing a nil value.let bin1 = as_bin!("age");match client.put(&policy, &key, &vec![&bin1]).await { Ok(()) => println!("Bin 'age' deleted"), Err(err) => println!("Error deleting bin: {}", err),};π API Reference:
Client::put
Modifying write behavior
The default behavior of a put() operation is:
- Create the record (if it doesnβt exist) in the cluster.
- Add the bins if they do not exist.
- Update bin values in the record (if the bins already exist).
- If the record has other bins, keep them in the record.
Use the WritePolicy to change write behavior. Some policy changes are:
- Only write if the record does not already exist:
- Set
policy.record_exists_actiontoRecordExistsAction::CreateOnly.
- Set
- Completely replace a record ONLY if it exists:
- Set
policy.record_exists_actiontoRecordExistsAction::ReplaceOnly
- Set
Writing record with time-to-live (TTL)
This example specifies a time-to-live value for a record on a write, setting the record expiration to two seconds:
let policy = WritePolicy::default();policy.expiration = Expiration::Seconds(2);match client.put(&policy, &key, &bins).await { Ok(()) => println!("All records written"), Err(err) => println!("Error writing records: {}", err),};π API Reference:
WritePolicy::default|Expiration|Client::put
Setting policy.expiration to certain specific values may have desirable side-effects, depending on your application.
| policy.expiration value | effect |
|---|---|
Expiration::NamespaceDefault | applies the default TTL on the server side each time a record updates. |
Expiration::Never | specifies that the record never expires. |
Expiration::DontUpdate | requests the server to update a record without changing itβs TTL. (Requires Aerospike Server version 3.10.1 or later.) |
If left unchanged from creation, the policy.expiration value defaults to Expiration::NamespaceDefault.
Read-modify-write
Record Read-Modify-Write (or Check-and-Set) involves:
- Reading the record, and remembering its generation value for later.
- Modifying the record at the application level.
- Setting
policy.generation_policytoGenerationPolicy::ExpectGenEqualwhile settingpolicy.generationto the previously set generation value.
This implements a form of optimistic locking; should the write operation fail, check for a generation error; if this error occurred, you know that the record was updated by another thread. This gives you the opportunity to retry the operation in the event of a collision. This is similar to load-linked/store-conditional optimistic mutual exclusion.
Complete example
The following complete program connects to Aerospike on localhost:3000, writes two records with name and age bins, applies a TTL of 10 seconds, and then closes the client connection.
use aerospike::{as_bin, as_key, Client, ClientPolicy, Error, Expiration, WritePolicy};
#[tokio::main]async fn main() -> Result<(), Error> { // Connect to Aerospike running on localhost. let client_policy = ClientPolicy::default(); let client = Client::new(&client_policy, &"127.0.0.1:3000").await?;
// Create records with bins name + age and a TTL of 10 seconds. let mut write_policy = WritePolicy::default(); write_policy.expiration = Expiration::Seconds(10);
let records = [("user-1", "Alice", 29), ("user-2", "Bob", 34)];
for (user_key, name, age) in records { let key = as_key!("test", "users", user_key); let bins = [as_bin!("name", name), as_bin!("age", age)]; client.put(&write_policy, &key, &bins).await?; println!("Created record: key={user_key}, name={name}, age={age}, ttl=10s"); }
// Close the connection. client.close().await?; println!("Connection closed");
Ok(())}π API Reference:
Client::new|WritePolicy::default|Expiration::Seconds|as_key!|as_bin!|Client::put|Client::close
Expected results
When the Aerospike server is running and reachable on 127.0.0.1:3000, output is similar to:
Created record: key=user-1, name=Alice, age=29, ttl=10sCreated record: key=user-2, name=Bob, age=34, ttl=10sConnection closed