ServiceStack redis,如何返回lua表作为列表



我正在使用ServiceStack的Redis客户端。我有一个LUA脚本,该脚本填满了Lua表,并带有重新调用的结果。我想以某种方式返回这张桌子。我的想法是使用client lib和lua脚本中的execluashaaslist方法,只是做一个"返回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
}

提示后更新答案

这是创建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();
    }

来自lua,您需要返回lua数组或json对象。" mytable"听起来像是一个只有LUA解释器内部有效的句柄。该手柄在通话后直接清理,因此不会传播给客户。

编辑:应支持一个简单的LUA表/数组。不确定那是怎么回事,而无需查看脚本。

另请参阅此链接,以获取有关LUA脚本原子性的一些额外信息。

希望这会有所帮助,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的解决方案给出了轻微的开销(但在编程时可能会更容易,并且是Nill-Safe)。

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-Programmer

在这里可以看到向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

最新更新