Skip to main content

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)
note

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, and addValue.

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