ServiceStack Redis,如何将Lua表作为列表返回

我正在使用ServiceStack的Redis客户端。我有一个Lua脚本,它使用几个Redis调用填充了一个Lua表中的结果。我想以某种方式返回此表。我的想法是使用客户端库中的ExecLuaShaAsList方法,在lua脚本中只需执行“返回myTable”。它不起作用,我总是得到一个空列表。

如何将lua表返回到redis客户端?

这是我使用Redis客户端的C#脚本:

使用(var redisClient = GetPooledRedisClient())
{
    var sha1 = redisClient.LoadLuaScript(luaBody);
    List<string> theList = redisClient.ExecLuaShaAsList(sha1);
    int listLength = theList.Count(); //由于某种原因,listLength始终为0
}

在下面的答案提示后更新

这是如何创建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(“结果[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(“ 如果fieldValue,则”);
     sb.AppendLine(“ result [categoriesToAggregate [i]] = result [categoriesToAggregate [i]] + fieldValue”);
     sb.AppendLine(“将”);
     sb.AppendLine(“ end”);
     sb.AppendLine(“ end”);
     sb.AppendLine(“ end”);
     sb.AppendLine();
     sb.AppendLine(“ return cjson.encode(result)”);

     返回sb.ToString();
}
点赞
用户2759336
用户2759336

从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

答案: 你不能在Lua返回值中返回嵌套值。就像你从ServiceStack函数中看到的一样,Lua脚本返回一个列表,而列表不是嵌套的。

以下是两个解决方案,其中JSON的解决方案会有轻微的overhead(但在编程时可能更容易,也可以安全地处理空值)。

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)

MsgPack也是一种非常好的紧凑序列化格式(我们经常使用它),可以这样返回:

a-alt:使用cmsgpack

return cmsgpack.pack(a)

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

这将返回:

_a_:

tw@srv-flux-02:~$ redis-cli -p 14312 EVAL "$(cat ~/tw_luatest.lua)" 0 0
"{\"47700415\":\"Hello\",\"47700415_000\":\"World\"}"

_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"

正如你所看到的,我在HSET中放了一些虚拟数据。

我还可以推荐这个链接,里面有一些好的信息:intro-to-lua-for-redis-programmers

在Lua字典中添加值的好方法可以在这里看到:efficient-index-type-operations-in-redis?rq=1

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
2014-03-09 20:35:16