I've created an aggregate function which works in aerospike which works in AQL:
AGGREGATE filter2.check_teamId('123', 0, 1456499994597) ON analytics.tracking
WHERE teamId = '123'
This returns results. I'm then trying to use the same UDF in NodeJS:
var statement = {
aggregationUDF: {module: 'filter2', funcname: 'check_teamId',
arg:['123', 0, 1456499994597]}
};
var query = client.query('analytics', 'tracking', statement);
var stream = query.execute();
The result is a seemingly uninformative error:
{ code: 100,
message: 'UDF: Execution Error 1',
func: 'as_query_aggregate',
file: 'src/main/aerospike/aerospike_query.c',
line: 903 }
The server logs state:
Feb 28 2016 22:33:58 GMT: INFO (scan): (scan.c::933) starting aggregation scan job 1201452721893048027 {analytics:tracking} priority 2
Feb 28 2016 22:33:58 GMT: INFO (scan): (scan.c::1026) finished aggregation scan job 1201452721893048027 (0)
Does anyone have any tips for getting a UDF to work with NodeJS? Or any ideas how to diagnose the error?
I have set the user UDF location in the config which does not affect the result.
UPDATE: Here is the lua code:
local function map_profile(record)
return map {interaction=record.interaction,
teamId=record.teamId, datetime=record.datetime,
timestamp=record.timestamp, version=record.version,
interactions=record.interactions}
end
function check_teamId(stream, teamId, startDate, endDate)
local function filter_teamId(record)
return record.teamId == teamId and
record.timestamp >= startDate and record.timestamp <= endDate
end
return stream : filter(filter_teamId) : map(map_profile)
end
The most likely reason that you are getting the UDF execution error (code: 100) is that the system and/or user path for the LUA subsystem are not setup correctly. If you turn on debug logging for the client you might see one or both of these error messages:
Apr 04 2016 08:15:19 UTC: DEBUG(45951) [conversions.cc:248] [config_from_jsobject] - Could not find a valid LUA system path ./aerospike-client-c/package/usr/local/aerospike/client/sys/udf/lua/
Apr 04 2016 08:15:19 UTC: DEBUG(45951) [conversions.cc:273] [config_from_jsobject] - Could not find valid LUA user path ./aerospike-client-c/package/usr/local/aerospike/client/usr/udf/lua
If the client cannot determine the correct path automatically, then you have to pass the system/user path in the configuration. (See below.)
But there is another problem with your UDF invocation in the Node.js client. The arguments for the UDF should be passed in the args
element of the aggregationUDF
object, not in arg
.
Here is a complete example that works for me:
const Aerospike = require('aerospike')
const config = {
hosts: '192.168.33.10:3000',
log: { level: 5 },
modlua: {
userPath: './',
systemPath: './node_modules/aerospike/aerospike-client-c/lua/'
}
}
Aerospike.connect(config, (error, client) => {
if (error) throw error
var statement = {
aggregationUDF: {
module: 'agg',
funcname: 'check_teamId',
args: ['123', 0, 1456499994597]
}
}
var query = client.query('test', 'tracking', statement)
var stream = query.execute()
var count = 0
stream.on('error', (error) => console.error('error:', error))
stream.on('data', (result) => {
count++
console.log('result:', result)
})
stream.on('end', () => {
console.log('found %d records', count)
client.close()
})
})
Note that this example uses the [email protected]
client version that was just released. But the setup and execution of a UDF query is identical with the v1.x client.
I have also uploaded this example to Github here. This Gist also includes a setup.js
script to create some sample records based on what your map_profile
function expects.
Feel free to follow up on this in our user forum. I'd love to hear if you got this to work for your application. (Or any other feedback about the Aerospike Node.js client!)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With