我正在使用ServiceStack的Redis客户端。我有一个Lua脚本,该脚本用多个Redis调用的结果填充Lua表。我想以某种方式返回此表。我的想法是使用客户端库中的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
}
提示后更新提示
这是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表/数组。不知道接下来发生了什么,而无需查看脚本。
另请参见此SO 链接,以获取有关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的解决方案会产生少量开销(但编程时可能会更容易,而且非常安全)。
答:使用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
返回:
一 :
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
。
我也可以推荐此链接,那里有一些不错的信息: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
问题内容: 在Python 2.7中,我可以将字典键,值或项作为列表获取: 现在,在Python> = 3.3中,我得到如下信息: 因此,我必须这样做以获得列表: 我想知道,是否有更好的方法在Python 3中返回列表? 问题答案: 尝试。 这会将对象转换为列表。 另一方面,你应该问自己是否重要。的编码方式是假设鸭子输入(如果看起来像鸭子,而像鸭子一样嘎嘎叫,那就是鸭子)。在大多数情况下,该对象的
问题内容: 当我通过redis EVAL运行此代码时,它不会返回任何结果。知道为什么这行不通吗? bug.lua 如果我初始化表,则仅打印该值。 问题答案: 如果您参考Redis 文档 ,则可以看到Redis将Lua表转换为Redis回复所使用的规则: Lua表(数组)-> Redis多批量回复( 如果有的话,将被截断为Lua数组中的第一个nil ) Lua表带有单个ok字段-> Redis状态回
问题内容: 我是Python的新手,需要将列表转换为字典。我知道我们可以将元组列表转换为字典。 这是输入列表: 并且我想将此列表转换为元组列表(或直接转换为字典),如下所示: 我们如何在Python中轻松做到这一点? 问题答案: 您想一次将三个项目分组吗? 您想一次分组N个项目吗?
问题内容: 如果我有一个,如何通过使用Java 8的功能将其转换为以相同的迭代顺序包含所有对象的? 问题答案: 你可以用于将内部列表(将它们转换为Streams之后)展平为单个Stream,然后将结果收集到列表中:
问题内容: 实现以下目标的Python方法是什么? 的每个成员都是一个元组,其第一个成员是,第二个成员是。 问题答案: 在Python 2中:
问题内容: 给定以下元组列表: 我如何将其拼凑成列表? 有没有一线做上面的事情? 问题答案: 您可以使用列表推导: 在以下情况下也经常使用: 但是,这并不是完全一样的。