How to add as_map to Large ordered list (llist)


#1

I want to add as_map to as_ldt type llist (large list). The documentation say below text for this:

Explicity - For value which are map/list/blob types, a map data structure with reserved field “key” has to be passed along with required value while inserting into LList collection. “key” may be an integer/string (this field is used for ordering and needs to be explicity specified).

I could not find any example for how to pass this key map structure to sever. I want to use “key” from my as_map as the ordering key for LLIST and it is string. Can you please suggest me how to do it using C APIs ?

Right now I am creating as_map and directly adding it to LLIST using aerospike_llist_add() api. I have followed the example given in the C client library code.


#2

Ganesh,

Key needs to be specified to make any entry into llist. If you have integer and string values you can simply do llist.add and the values themselves will be taken as keys.

Now for the case where you want to insert a map. Map/List cannot act as a key so you need to specify the keys for the map value.

If you want to insert values {“a”:10} what you need to create map with an entry with keyword key along with value of interest. e.g value into LLIST could be {“key”: 1, “a”:10} or {“key”:1, “value”:{“a”:10}}

This would make entry as 1 -> value

When you request a value using llist.find you will get {“key”:1 “a”:10} or {“key”:1, “value”:{“a”:10}] based on values you inserted.

C code would something like this

lmap_put_function(as_aerospike as, as_key *reckey, as_ldt llist, as_val *itemkey, as_map *mapval) {
  
    as_error err;
    as_error_reset(&err);

    as_hashmap map;
    as_hashmap_init(&map, 2);
    
    as_hashmap_set(as_string_new_strdup("key"), itemkey);
    as_hashmap_set(as_string_new_strdup("v"), mapval);
    
    aerospike_lmap_put_all(as, &err, NULL, &reckey, llist, (as_map*)&map)

HTH

– R


#3

Hi Raj,

Thanks for the reply. It really helped me to move forward. But now I am facing new problem with llist and map. Here are the details:

As per your description above, if I have to add value {“a”: 10}, then I have to insert {“key”: “a”, “a”:10} into LLIST. To do this I have added below C code and it works fine:

    as_error err;
    as_error_reset(&err);

    as_hashmap map;
    as_map *m = (as_map *)as_hashmap_init(&map, 2);
    as_stringmap_set_str(m, "key", "a");
    as_stringmap_set_int64(m, "a", "10");

    as_ldt llist;
    as_ldt_init(&llist, "myllist", AS_LDT_LLIST, NULL)

    aerospike_llist_add(&as, &err, NULL, &reckey, &llist, (as_val *)m);

This ({“a”: “10”}) map is successfully inserted to LLIST. I verified it using aql tool. If I do the llist.find(‘myllist’, ‘a’), then I get the map.

Now I have multiple such maps which I want to insert into LLIST.

Eg. [{“k1”: 1}, {“k2”: 2}, {“k3”: 3}…{“kn”: n}]

To add these map entries into LLIST I have to create below map structure:

[{“key”: “k1”, “k1”: 1}, {“key”: “k2”, “k2”: 2}, {“key”: “k3”, “k3”: 3}…{“key”: “kn”, “kn”: n}]

I have added below C code to do this:

as_error err;
as_error_reset(&err);

map_array[n] // This is my map array which is properly initialized with unique key and value

as_arraylist vals;
as_arraylist_inita(&vals, n);

for(int k = 0; k < n; ++k) {
    as_hashmap map1;
    as_map *m1 = (as_map *)as_hashmap_init(&map1, (2));
    as_stringmap_set_str(m1, "key", map_array[k].key);
    as_stringmap_set_int64(m1, map_array[k].key, map_array[k].value);
    as_arraylist_append_map(&vals, m1);
}

if (aerospike_llist_add_all(&as, &err, NULL, &reckey, &llist, (as_list *)&vals) != AEROSPIKE_OK)
{           
    printf("aerospike_llist_add_all() returned %d - %s", err.code, err.message);
}

Ideally this code should insert all the map values to LLIST, but it fails with error message:

 aerospike_llist_add_all() returned 100 - /opt/aerospike/sys/udf/lua/ldt/lib_llist.lua:5528: 1402:LDT-Unique Key or Value Violation

If I do single map add at time using aerospike_llist_add() then it works fine for all the map entries. But it will be performance hit to do it one by one. I want to do it in a single call to Aerospike Server

Can you please tell me why this error message is coming ? Or am I missing anything here? Or tell me the right way to do it.


#4

Ganesh,

Append to list is by reference not by value. You should use new.

for(int k = 0; k < 10; ++k) {
    as_map *m1 = (as_map *)as_hashmap_new((2));
    as_stringmap_set_int64(m1, "key", k);
    as_stringmap_set_int64(m1, "v", k);
    as_arraylist_append_map(&vals, m1);
}

You code is actually most likely ending up somehow having val in list pointing to same map.

– R


#5

Hi Raj,

Thanks for the details. This fix worked fine. But Ideally the original code should work.

I am using C client API through C++ code. I tried to find the root cause of this issue. Below are the details:

for(int k = 0; k < n; ++k) {
    as_hashmap map1;
    as_map *m1 = (as_map *)as_hashmap_init(&map1, (2));
    as_stringmap_set_str(m1, "key", map_array[k].key);
    as_stringmap_set_int64(m1, map_array[k].key, map_array[k].value);
    as_arraylist_append_map(&vals, m1);
}

In this for loop I printed the address of “m1” and found that it gets same address every time (for k = 0…n-1). It might be optimization from g++ compiler. In the as_arrarylist_append_map() call it just stores the address of as_val. So in my case there are multiple map entries in the as_arraylist but all of them having the same address and same content also (key and value for (n-1)th) entry. That’s why it gives Unique key or value violation error.

Why are your storing only the address ? why not value ?

If you have done it purposefully, then your documentation should mention that “use only heap allocated data types while storing the elements into arraylist”. Otherwise many users will face this issue.


largeMap udf with node.js client
#6

Why are your storing only the address ? why not value ?

Deep copy is very costly. So basic operation does not do it. But these values are refcounted so even if you free it somewhere else the val will survive till list nukes it !!

– R


#7

Ganesh,

We will update our documentation make this clear !!!

– R