【问题标题】:Redis: How to HMSET a dictionary from a Lua script?Redis:如何从 Lua 脚本 HMSET 字典?
【发布时间】:2020-03-18 20:18:04
【问题描述】:

我正在尝试将 Python dict 作为参数传递给 Lua 脚本,并将 HMSET 传递给脚本中的 Redis 键。

我有两个问题。

我应该如何将 dict 从 Python 传递到 Lua 脚本以及从 Lua 脚本传递到 Redis?

使用json.dumps() 将其传递给 Lua 似乎很简单。但是,如何将它转换回 Lua 中的 dict(或者我猜是 Lua 表?)(我不能在 Redis 的 EVAL 中使用 Lua 的 require)。

虽然我仍然不知道如何将真正的 dict 从 Lua 传递给 Redis,但我仍然在 Lua 脚本中使用 HMSET 并尝试为键分配一个字符串。

为什么会出现此错误:

redis.exceptions.ResponseError: Error running script (call to f_2591f0a1987b36dd027b752af3591c92be845cd4):
@user_script:7: @user_script: 7: Wrong number of args calling Redis command From Lua script

前提是我的 Lua 代码使用与我的 Python HMSET 相同数量的 args:

local key_name = KEYS[1]
redis.call('hmset', key_name, "some_val")

【问题讨论】:

    标签: python redis lua nosql lua-table


    【解决方案1】:

    首先,请注意 Pythonic dict 与 Redis Hash 相同:虽然 dict 可以将任何类型存储为值并支持嵌套,但哈希只有 1 级深度并存储字符串.因此,如果您的 dict 是嵌套的和/或包含非字符串值,则映射是非平凡的。

    现在,假设 dict 确实是非嵌套的。

    我应该如何将 dict 从 Python 传递到 Lua 脚本以及从 Lua 脚本传递到 Redis?

    当您传递 JSON 化表示时,您可以使用 Redis' Lua cjson library 将其解析为 Lua 表,如下所示:

    local dict = cjson.decode(ARGS[1])
    

    为什么会出现这个错误:

    引发错误是因为您在没有字段名称参数的情况下调用 HMSET(顺便说一句,已弃用,由 HSET 代替)。一个正确的方法(即将字典保存到哈希)如下所示:

    local key_name = KEYS[1]
    local dict = cjson.decode(ARGS[1])
    for k, v in pairs(dict) do
      redis.call('HSET', key_name, k, v)
    end
    

    或者这个稍微快一点的变体:

    local key_name = KEYS[1]
    local dict = cjson.decode(ARGS[1])
    local payload = {}
    for k, v in pairs(dict) do
      table.insert(payload, k)
      table.insert(payload, v)
    end
    redis.call('HSET', key_name, unpack(payload))
    

    【讨论】:

    • 谢谢。但是我实际上在HMSET中指定了字段名,就是key_name。知道为什么它不起作用吗?
    • 您需要为HSET 指定键、字段和值 - 您只提供了三个中的两个。
    • key和field有什么区别?通过使用相同的表达式,例如redis.call('hmset', key_name, "some_val") 我设法将它设置为没有错误,只需将“some_val”替换为我从现有 Redis 键中获得的值。这让我感到困惑,因为在这种情况下,我保持参数的数量相同,但错误不存在。
    • 一个key标识了Redis中的一个值。该值可以是不同的类型 - 即字符串、列表、哈希。在哈希值中(在单个键下),您可以拥有一个或多个字段值对。如果不提供键名和(至少)一个字段值对(使“redis.call”命令的参数总数为 4,包括“hmset”,我看不出它是如何工作的命令本身)。
    • 哦,我明白了。似乎混乱来自我使用的 Redis-Py 确实有两个参数:hmset(name, mapping) - 后者是 Python 字典。似乎在 Lua 脚本中最终对我有用:redis.call('HMSET', key_name, unpack(tmp_val)) 起作用了,因为unpack 返回关联数组的解压缩值列表。谢谢,我接受你的回答。
    猜你喜欢
    • 2017-06-05
    • 2013-08-28
    • 2016-03-22
    • 1970-01-01
    • 1970-01-01
    • 2019-08-28
    • 2014-12-02
    • 2013-09-12
    • 1970-01-01
    相关资源
    最近更新 更多