Skip to content
Visit booth 3171 at Google Cloud Next to see how to unlock real-time decisions at scaleMore info

Bin operations

Applications can perform separate modification commands on multiple bins in a record within a single command using the Aerospike C client. This also allows modification of the bins of a record, which is returned back with the command’s result (that is, it allows an application to perform an atomic modification that returns the result).

The following operations can be performed on a record:

OperationDescriptionConditions
writeWrite a value to a bin.
readRead the value of a bin.
incrementIncrement the integer value of a bin.Only integer values.
appendAppend a value to the value of a bin.The value must be the same data type as the value in the bin; only bytes or strings are valid types.
prependPrepend a value to the value of a bin.The value must be the same data type as the value in the bin; only bytes or strings are valid types.
deleteDelete an entire record
touchUpdate the generation value of the record.
listOperations on a list bin. See List Operations.
mapOperations on a map bin. See Map Operations.

Tracking Page Views

The following application tracks the page views of a website. The key is the URL for a page. The record contains the following bins:

  • last-updated (integer) — The time this record last updated.
  • views (integer) — The number of page view entries.
  • addr (byte array) — A sequence of IP address strings, delimited by NULL.
  • user (byte array) — A sequence of user ID strings, delimited by NULL.
  • time (byte array) — A sequence of timestamp strings, delimited by NULL.

The addr, user, and time bins are sequences of NULL-separated strings. The entries in addr, user, and time are in sync, such that a single page view is the value at the same index of each bin.

as_operations ops;
as_operations_inita(&ops, 5);
as_operations_add_write_int64(&ops, "last-updated", timestamp);
as_operations_add_incr(&ops, "views", 1);
as_operations_add_append_raw(&ops, "addr", (uint8_t*)addr, strlen(addr) + 1);
as_operations_add_append_raw(&ops, "user", (uint8_t*)user, strlen(user) + 1);
as_operations_add_append_raw(&ops, "time", (uint8_t*)time, strlen(time) + 1);
as_key key;
as_key_init(&key, "app", "pages", url);
if (aerospike_key_operate(&as, &err, NULL, &key, &ops, &rec) != AEROSPIKE_OK) {
fprintf(stderr, "err(%d) %s at [%s:%d]\n", err.code, err.message, err.file, err.line);
}
as_operations_destroy(&ops);

Increment-and-Read Commands

A common sequence of operations is increment-and-read. This allows an application to use a counter and read the values after each increment.

The following example is a page-view counter. The key of the record is the URL. The bin containing the counter is views.

as_operations ops;
as_operations_inita(&ops, 2);
as_operations_add_incr(&ops, "views", 1);
as_operations_add_read(&ops, "views");
as_record _rec;
as_record *rec = as_record_inita(&_rec, 1);
as_key key;
as_key_init(&key, "app", "pages", url);
if (aerospike_key_operate(&as, &err, NULL, &key, &ops, &rec) != AEROSPIKE_OK) {
fprintf(stderr, "err(%d) %s at [%s:%d]\n", err.code, err.message, err.file, err.line);
}
else {
printf("views = %ld\n", as_record_get_int64(rec, "views", 0));
}
as_record_destroy(rec);
as_operations_destroy(&ops);

Touching a Record

Each record contains metadata such as time-to-live and generation. The generation can be considered the version number of the record that increments with each update. The TTL is the time until the record expires. When reading a record, these values are not modified. So, if a record has a TTL of 5 minutes, even if it is constantly read, after 5 minutes it is no longer available. To keep the record from expiring, use the touch operation on the record.

The following example reads three bins and touches a record to prevent it from expiring. To read the three bins from the database, initialize a record with capacity for three bins.

as_operations ops;
as_operations_inita(&ops, 4);
as_operations_add_touch(&ops);
as_operations_add_read(&ops, "x");
as_operations_add_read(&ops, "y");
as_operations_add_read(&ops, "z");
as_record _rec;
as_record *rec = as_record_inita(&_rec, 3);
as_key key;
as_key_init(&key, "app", "pages", url);
if (aerospike_key_operate(&as, &err, NULL, &key, &ops, &rec) != AEROSPIKE_OK) {
fprintf(stderr, "err(%d) %s at [%s:%d]\n", err.code, err.message, err.file, err.line);
}
else {
printf("x = %ld\n", as_record_get_int64(rec, "x", 0));
printf("y = %ld\n", as_record_get_int64(rec, "y", 0));
printf("z = %ld\n", as_record_get_int64(rec, "z", 0));
}
as_record_destroy(rec);
as_operations_destroy(&ops);

See examples/basic_examples/touch in the Aerospike C client package for examples of using aerospike_key_operate().

Multiple Results for the Same Bin

When multiple operations are performed on the same bin in the same record, the results are returned in a results array. The array order is the same as the user-defined operation order.

This map example populates a hashmap bin and then performs various rank operations on that map.

// Write map.
as_key rkey;
as_key_init_int64(&rkey, "test", "set", 4);
as_operations ops;
as_operations_inita(&ops, 1);
as_map_policy mode;
as_map_policy_init(&mode);
as_hashmap item_map;
as_hashmap_init(&item_map, 4);
as_string mkey1;
as_integer mval1;
as_string_init(&mkey1, "Charlie", false);
as_integer_init(&mval1, 55);
as_hashmap_set(&item_map, (as_val*)&mkey1, (as_val*)&mval1);
as_string mkey2;
as_integer mval2;
as_string_init(&mkey2, "Jim", false);
as_integer_init(&mval2, 98);
as_hashmap_set(&item_map, (as_val*)&mkey2, (as_val*)&mval2);
as_string mkey3;
as_integer mval3;
as_string_init(&mkey3, "John", false);
as_integer_init(&mval3, 76);
as_hashmap_set(&item_map, (as_val*)&mkey3, (as_val*)&mval3);
as_string mkey4;
as_integer mval4;
as_string_init(&mkey4, "Harry", false);
as_integer_init(&mval4, 82);
as_hashmap_set(&item_map, (as_val*)&mkey4, (as_val*)&mval4);
as_operations_add_map_put_items(&ops, "mapbin", &mode, (as_map*)&item_map);
as_error err;
as_record* rec = NULL;
as_status status = aerospike_key_operate(&as, &err, NULL, &rkey, &ops, &rec);
as_operations_destroy(&ops);
if (status != AEROSPIKE_OK) {
return status;
}
as_record_destroy(rec);
// Perform rank operations.
as_operations_inita(&ops, 2);
// Get lowest score.
as_operations_add_map_get_by_rank(&ops, "mapbin", 0, AS_MAP_RETURN_VALUE);
// Get name/score of person with highest score.
as_operations_add_map_get_by_rank(&ops, "mapbin", -1, AS_MAP_RETURN_KEY_VALUE);
rec = NULL;
status = aerospike_key_operate(&as, &err, NULL, &rkey, &ops, &rec);
as_operations_destroy(&ops);
if (status != AEROSPIKE_OK) {
return status;
}
as_bin* results = rec->bins.entries;
// First operation result contains lowest score.
int64_t lowest_score = results[0].valuep->integer.value;
// Second operation result contains name/score of person with highest score.
// The list contains two items, name and score.
as_list* list = &results[1].valuep->list;
const char* name = as_list_get_str(list, 0);
int64_t score = as_list_get_int64(list, 1);
printf("Highest score: %s/%d Lowest score: %d\n", name, (int)score, (int)lowest_score);
as_record_destroy(rec);

Deleting an Entire Record

as_operations ops;
as_operations_inita(&ops, 2);
as_operations_add_read(&ops, "bin1");
as_operations_add_delete(&ops);
if (aerospike_key_operate(&as, &err, NULL, &key, &ops, &rec) != AEROSPIKE_OK) {
fprintf(stderr, "err(%d) %s at [%s:%d]\n", err.code, err.message, err.file, err.line);
}
as_operations_destroy(&ops);

See examples/basic_examples/touch in the Aerospike C client package for examples of using aerospike_key_operate().

Feedback

Was this page helpful?

What type of feedback are you giving?

What would you like us to know?

+Capture screenshot

Can we reach out to you?