ServiceStack Redis,如何将Lua表作为列表返回 [英] ServiceStack Redis, how to return Lua table as List

查看:433
本文介绍了ServiceStack Redis,如何将Lua表作为列表返回的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用ServiceStack的Redis客户端.我有一个Lua脚本,该脚本用多个Redis调用的结果填充了Lua表.我想以某种方式返回此表.我的想法是使用客户端库中的ExecLuaShaAsList方法,并在lua脚本中执行"return myTable".它不起作用,我总是返回一个空列表.

I'm using the Redis client from ServiceStack. I have a Lua script that fills up a Lua table with results from several Redis calls. I want to return this table in some way. My thought was to use the method ExecLuaShaAsList from the client lib and in the lua script just do a "return myTable". It doesnt work, I always get an empty list back.

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

How to return the lua table to the redis client?

这是我与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解释器内部有效的句柄.该句柄将在调用后立即清理,因此不会传播到客户端.

From Lua, you need to return a Lua Array, or a JSON object. 'myTable' sounds like a handle that is only valid inside the Lua interpreter. That handle is cleaned up directly after the call, so won't get propagated to the client.

应该得到支持.不知道正在发生什么,而无需查看脚本.

a simple Lua Table/Array should be supported. Not sure what's going on then, without looking at the script.

另请参见此

See also this SO link for some extra info about atomicity of Lua scripts.

希望这对您有帮助,TW

Hope this helps, 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脚本返回一个列表,并且列表没有嵌套.

Answer: You can't return nested values in the Lua return value. As you can see from your ServiceStack function, a Lua script returns a list, and a list is not nested.

这里有两种解决方案,一种采用JSON的解决方案会产生少量开销(但是编程时可能会更容易,而且非常安全).

Here are two solutions, the one with JSON gives slight overhead (but might be easier when programming, and is 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 也是一种非常不错且紧凑的序列化格式(我们经常使用),可以返回像这样:

MsgPack is also a very nice and compact serialization format (we use it a lot), and can be returned like this:

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中放入了一些虚拟数据.

As you can see, I put some dummy data in the HSET.

我也可以推荐此链接,其中有一些不错的信息:

I can also recommend this link, some nice info in there: intro-to-lua-for-redis-programmers

可以看到一种向Lua字典添加值的好方法这里:

A nice way of adding values to a Lua dict can be seen here :

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

这篇关于ServiceStack Redis,如何将Lua表作为列表返回的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆