我有一个带代码块的lua脚本,如下所示:
local call_data = cjson.decode(ARGV[1]) local other_data = cjson.decode(ARGV[2]) local data = {} local next = next local populate_data = function(source) if next(source) == nil then return end for property,value in pairs(source) do redis.call('HSET', KEYS[2], property, value) end end populate_data(call_data) populate_data(other_data)
当我尝试使用以下命令KEYS和ARGV运行脚本时:-
redis-cli --eval dialed.lua "inflight_stats:18" "calls:AC443d7a8111a96ba8074f54a71f0521ce:CA1ec49703eee1959471c71506f43bb42e:dialed" , "{\"from\":\"+18035224181\",\"to\":\"+919943413333\",\"sid\":\"CA1ec49703eee1959471c71506f43bb42e\",\"status\":\"queued\",\"direction\":\"outbound-api\",\"date_created\":null,\"account_sid\":\"AC443d8a8111a96ba8074f54a71f0521ce\"}" "{\"phone\":\"919943413333\",\"campaign_id\":18,\"caller_session_sid\":\"CA828b163153bf5cc301ef5285e38925f9\"}" 0
错误:-
(error) ERR Error running script (call to f_08dcc69ee8baa0200e0cf552948ab4bc338c9978): @user_script:11: @user_script: 11: Lua redis() command arguments must be strings or integers
TL; DR表示由返回的值cjson.decode(),用于cjson.null与JSON的null值进行比较。
cjson.decode()
cjson.null
null
说明:Lua nil在表中用于标记已删除的条目。如果将JSONinc null转换为Lunatic nil,则解码的对象将损坏。因此,cjson lib使用轻量级的userdata类型表示null/ nil。
nil
您的“ call_data”具有一个“ date_created”字段,该字段为null-导致错误。
有趣的是,Redis与Lua一样,不会存储nil / null值,因此您必须忽略null值,或者在Redis中使用特殊值来标记它们。
假设您将忽略它们,这是一种解决方法:
local call_data = cjson.decode(ARGV[1]) local other_data = cjson.decode(ARGV[2]) local data = {} local next = next local null = cjson.null local populate_data = function(source) if next(source) == nil then return end for property,value in pairs(source) do if value ~= null then redis.call('HSET', KEYS[2], property, value) end end end populate_data(call_data) populate_data(other_data)
另外,一个小的优化将是批量更新,如下所示:
local payload = {} for property,value in pairs(source) do if value ~= null then table.insert(payload, property) table.insert(payload, value) end end redis.call('HSET', KEYS[2], unpack(payload))
PS,如果您愿意的话,请看一下我编写的ReJSON-它旨在帮助您解决您试图做的事情。