Apply a UDF
Single record
UDFs that execute on a single record are Record UDFs. The record may or may not exist in the database, which allows the UDF to update or create a record.
To invoke a Record UDF using Client.execute_udf
:
Client.execute_udf(
key,
packageName,
functionName,
args = [],
opts = {}
)
Where:
key
— The key of the record on which to invoke the function.packageName
— The UDF module that contains the function to invoke.functionName
— The function to invoke.args
— The function arguments.opts
— The policy options.
This example defines a UDF in the module examples.lua:
function readBin(r, name)
return r[name]
end
readBin
returns the value of record r in bin name.
The client application can invoke readBin
on a record:
result = client.execute_udf(key, "examples", "readBin", ["name"])
key
specifies the record to pass to the UDF as the parameter r
.
Multiple Arguments
If the UDF accepts multiple arguments, add each argument to Client.execute_udf
.
For example, if the following UDF is defined in example.lua:
function multiplyAndAdd(r, a, b)
return r['factor'] * a + b;
end
(This multiplies the bin factor by a and adds b, and returns results to the caller.)
Then, to invoke multiplyAndAdd()
from Ruby, run:
result = client.execute_udf(key, "examples", "multiplyAndAdd", [10, 5])
Transform
Use the Aerospike Ruby client ability to scan records in the database and transform each record using User-Defined Functions (UDFs).
In SQL, you perform transformation on all rows in a table as an UPDATE statement without predicates:
UPDATE test.demo
SET a = 1, b = 2
WHERE c = 3
Aerospike provides a similar capability, but allows you to transform records by applying a Record UDF function on each record. A Record UDF is applied to individual records. It can be provided as arguments, and can read and write the bins of a record and perform calculation. Refer to the QueryExecute
example in the examples package.
Defining Record UDFs
The following is the processRecord
Record UDF defined in record_example.lua, where:
- The record contains two integer bins: name1 and name2.
- For name1 even integers, add the value to the existing name1 bin.
- For name1 integers with a multiple of 5, delete the name2 bin.
- For name1 integers with a multiple of 9, delete the record.
function processRecord(r, name1, name2, addValue)
local v = r[name1]
if (v % 9 == 0) then
aerospike:remove(r)
return
end
if (v % 5 == 0) then
r[name2] = nil
aerospike:update(r)
return
end
if (v % 2 == 0) then
r[name1] = v + addValue
aerospike:update(r)
end
end
Registering UDFs
After defining the UDF function, it must register with the Aerospike cluster. See Register UDF.
Initializing the Query Statement
To initialize a query statement:
stmt = Statement.new(namespace, set, [binName1])
stmt.filters << Filter.Range(binName1, begin, end)
If there is no value for Filter
, the UDF function is applied to all records in the database. You must supply the corresponding secondary index for the specified bin. See Manage Indexes.
Executing a UDF on a Record
To execute UDFs using #execute_udf_on_query
:
task = client.execute_udf_on_query(stmt,
'record_example', 'processRecord', [binName1, binName2, 100])
Where,
stmt
— Specifies the set of records for the UDF.record_example
— Specifies the UDF module.processRecord
— Specifies the function to use on each record.- These parameters passthrough to the UDF function:
name1
,name2
, andaddValue
.
Determining UDF Processing Status
To inform the application of job status, call #wait_till_completed
in the task periodically:
# to block until the UDF is run on all records in query
task.wait_till_completed
# task is completed successfully