Tho*_*mas 6 lua redis lua-table
我正在使用ServiceStack的Redis客户端.我有一个Lua脚本,用几个Redis调用的结果填充一个Lua表.我想以某种方式返回此表.我的想法是使用来自客户端lib的方法ExecLuaShaAsList,并在lua脚本中执行"return myTable".它不起作用,我总是得到一个空列表.
如何将lua表返回给redis客户端?
这是我与Redis客户端一起使用的C#脚本:
using (var redisClient = GetPooledRedisClient())
{
var sha1 = redisClient.LoadLuaScript(luaBody);
List<string> theList = redisClient.ExecLuaShaAsList(sha1);
int listLength = theList.Count(); //listLength is always 0 for some reason
}
Run Code Online (Sandbox Code Playgroud)
从以下答案后提示更新
这就是LuaBody的创建方式:
private string GetLuaScript(List<CatalogItem> categories, List<CatalogItem> products)
{
string categoriesToAggregate = string.Join("\",\"", categories.Select(c=>c.Name));
categoriesToAggregate = "\"" + categoriesToAggregate + "\"";
string csSearchResult = string.Join("\",\"", products.Select(c => c.Name));
csSearchResult = "\"" + csSearchResult + "\"";
StringBuilder sb = new StringBuilder();
sb.AppendLine("local categoriesToAggregate = {").Append(categoriesToAggregate).Append("} ");
sb.AppendLine("local csSearchResult = {").Append(csSearchResult).Append("} ");
sb.AppendLine("local result = {} ");
sb.AppendLine();
sb.AppendLine("for i=1,#categoriesToAggregate do ");
sb.AppendLine(" result[categoriesToAggregate[i]] = 0 ");
sb.AppendLine();
sb.AppendLine(" for j=1,#csSearchResult do ");
sb.AppendLine(" local fieldValue = redis.call('hget', 'asr:'..csSearchResult[j], categoriesToAggregate[i]) ");
sb.AppendLine(" if fieldValue then ");
sb.AppendLine(" result[categoriesToAggregate[i]] = result[categoriesToAggregate[i]] + fieldValue ");
sb.AppendLine(" end ");
sb.AppendLine(" end ");
sb.AppendLine("end ");
sb.AppendLine();
sb.AppendLine("return cjson.encode(result) ");
return sb.ToString();
}
Run Code Online (Sandbox Code Playgroud)
从Lua,您需要返回Lua数组或JSON对象.'myTable'听起来像一个只在Lua解释器中有效的句柄.该句柄在调用后直接清理,因此不会传播到客户端.
编辑:应支持简单的Lua表/数组.不知道发生了什么,不看脚本.
有关Lua脚本的原子性的一些额外信息,请参阅此SO 链接.
希望这有帮助,TW
编辑OP后:
这是OP的原始Lua脚本:
local a={}
for i = 1, 1, 1 do
a["47700415"] = redis.call('hget', 'asr:47700415', 'MDEngines')
a["47700415_000"] = redis.call('hget', 'asr:47700415_000', 'MGEngines')
end
return a
Run Code Online (Sandbox Code Playgroud)
答案:您无法在Lua返回值中返回嵌套值.从ServiceStack函数中可以看出,Lua脚本返回一个列表,并且列表不是嵌套的.
这里有两个解决方案,一个带有JSON的解决方案会带来轻微的开销(但在编程时可能更容易,并且是非常安全的).
a:使用cjson
local a={}
for i = 1, 1, 1 do
a["47700415"] = redis.call('hget', 'asr:47700415', 'MDEngines')
a["47700415_000"] = redis.call('hget', 'asr:47700415_000', 'MGEngines')
end
return cjson.encode(a)
Run Code Online (Sandbox Code Playgroud)
MsgPack也是一个非常好的和紧凑的序列化格式(我们经常使用它),可以像这样返回:
a-alt:使用cmsgpack
return cmsgpack.pack(a)
Run Code Online (Sandbox Code Playgroud)
b:使用简单的数组
local a={}
for i = 1, 1, 1 do
a[1] = "47700415"
a[2] = redis.call('hget', 'asr:47700415', 'MDEngines')
a[3] = "47700415_000"
a[4] = redis.call('hget', 'asr:47700415_000', 'MGEngines')
end
return a
Run Code Online (Sandbox Code Playgroud)
返回:
一个:
tw@srv-flux-02:~$ redis-cli -p 14312 EVAL "$(cat ~/tw_luatest.lua)" 0 0
"{\"47700415\":\"Hello\",\"47700415_000\":\"World\"}"
Run Code Online (Sandbox Code Playgroud)
b:
tw@srv-flux-02:~$ redis-cli -p 14312 EVAL "$(cat ~/tw_luatest2.lua)" 0 0
1) "47700415"
2) "Hello"
3) "47700415_000"
4) "World"
Run Code Online (Sandbox Code Playgroud)
如你所见,我把一些虚拟数据放入HSET.
我也可以推荐这个链接,其中有一些不错的信息:intro-to-lua-for-redis-programmers
在这里可以看到为Lua dict添加值的好方法:
local fkeys = redis.call('sinter', unpack(KEYS))
local r = {}
for i, key in ipairs(fkeys) do
r[#r+1] = redis.call('hgetall',key)
end
return r
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3832 次 |
| 最近记录: |