Storing new record key with UDF create


#1

Is there an equivalent of the Java writePolicy.sendKey=true when creating a new record with UDF via aerospike:create(rec)? Is there a consistent way of doing that or do I manually pass in the keyValue into the udf and do a rec['key'] = keyValue?

Thanks!


#2

Naoum,

User does not have control of setting the key (of the record) like this. What you are doing above is actually setting value of keyValue in the bin ‘key’.

Just pass the same policy while request UDF execution. System will automatically store key along with the record.

– R


#3

@raj

Thanks for your reply! I am infact using the same policy when calling the execute() call but it doesn’t affect the record created with the UDF. Here’s my test example that I’ve been using:

    keyValue = "user1";
    binName = "testBin";
    valueMap = ImmutableMap.of("test", 1);

    Map.Entry<String, ?> entry = valueMap.entrySet().iterator().next();
    Key udfKey = new Key(nsName, setName, keyValue + "_udf");
    aerospikeClient.execute(writePolicy, udfKey, "map_ops", "updateMap",
                Value.get(binName), Value.get(entry.getKey()), Value.get(entry.getValue()));

    System.out.println("Stored with udf " + Buffer.bytesToHexString(udfKey.digest) + ", sendKey=" + writePolicy.sendKey);

    Key putKey = new Key(nsName, setName, keyValue + "_put");
    aerospikeClient.put(writePolicy, putKey, Bin.asMap(binName, valueMap));
    System.out.println("Stored with put " + Buffer.bytesToHexString(putKey.digest) + ", sendKey=" + writePolicy.sendKey);

    aerospikeClient.scanAll(null, nsName, setName, new ScanCallback() {
        @Override public void scanCallback(Key key, Record record) throws AerospikeException {
            System.out.println("key: " + key.toString() + ", record:" + record.toString());
        }
    });

The udf used is a generic update or create a map entry from https://github.com/adform/trident-aerospike/blob/master/udf/map_ops.lua

This produces the output (note user1_put vs null in the key):

Stored with udf e26dc422ffd6d0fbb22d58119fec48a7282d02aa, sendKey=true
Stored with put 19d1937188e557ef9cdec8277cb59438f206ed2a, sendKey=true
key: teststore:keytest:user1_put:19d1937188e557ef9cdec8277cb59438f206ed2a, record:(gen:1),(exp:184781343),(bins:(testBin:{test=1}))
key: teststore:keytest:null:e26dc422ffd6d0fbb22d58119fec48a7282d02aa, record:(gen:1),(exp:0),(bins:(testBin:{test=1}))

And similarly with aql you can see the key for one but not the other:

select * from teststore.keytest
+-------------+------------+
| key         | testBin    |
+-------------+------------+
| "user1_put" | {"test":1} |
|             | {"test":1} |
+-------------+------------+

Am I missing anything?

P.S. I guess the same applies for the TTL sent (I assume that’s what exp:184781343 means)


#4

You want to make sure that the writePolicy used on the aerospikeClient.execute() call has the “sendKey=true” turned on:

writePolicy.sendKey = true;
aerospikeClient.execute(writePolicy, udfKey, "map_ops", "updateMap",
                Value.get(binName), Value.get(entry.getKey()), Value.get(entry.getValue()));

And also that the record does not already exist.

You can also modify the “WriteUsingUDF” Java example and add writePolicy.sendKey=true

You will see the key is being stored.


#5

@wchu,

Thanks for taking a look. If you note the logs I provided above I do log the value of sendKey and it’s true for both queries (I also tried hardcording it as you suggested but got the same behavior). I also made sure to delete pre-existing records before running the code sample, and as you can see from the generation in the log output (gen:1) it was freshly created. I also tried using a key name that did not previously exist at all and got the same behavior. Are there any server config settings or anything else that’s in play when it comes to this? Is there a way to log the policy from the UDF to confirm if it has the right attributes there? Anything else I can do to tell where it is getting lost?

Thanks, Naoum


#6

When you modify the Java UDF example and put in the sendKey=true, what do you get as the result?

This is the result we get, and the key is stored:

aql> select udfbin3 from test
+-----------+---------+
| key       | udfbin3 |
+-----------+---------+
| "udfkey3" | "first" |
+-----------+---------+

1 rows in set (0.069 secs)


#7

Doh! Looks like that might have been a change/bug in the java client - I was previously using the java client 3.0.30 and just updated it to the latest (3.1.4) and now it works.

Thanks for your help!