使用 LUA 脚本在 Redis 中修改对象

请帮忙出出主意,关于在 Redis 中使用 LUA 脚本修改对象的问题。 我有一个 Redis 列表,其中包含以下实体:

{
  "@class": "com.myproject.model.Book",
  "bookId": "someId",
  "author": "someAuthor"
}

现在,我需要更改实体以允许为某些书籍拥有多个作者,并创建迁移脚本:

{
  "@class": "com.myproject.model.Book",
  "bookId": "someId",
  "authors":  [
           "java.util.ArrayList",
            [
              "someAuthor"
            ]
         ]
}

我认为我需要在 LUA 中执行以下操作:

local book
local cacheName --缓存名称
local authorId;

local size = redis.call('LLEN', cacheName)
if size == 0
then
    return -1
end

while size > 0
do
    book = redis.call('LPOP', cacheName)

    -- 在这里修改实体

    affectedEntitiesCount = affectedEntitiesCount + 1
    redis.call('RPUSH', cacheName, book)
    size = size - 1
end
return affectedEntitiesCount

但我不知道如何根据要求修改书籍对象。 能否有人帮忙看一下并提供建议?

点赞
用户12080584
用户12080584
local book
local cacheName
local authorPattern= '"author":"[^"]*"'
local authorId
local replacementAuthors = '"authors":["java.util.ArrayList",["%s"]]'

local size = redis.call('LLEN', cacheName)
if size == 0
then
    return -1
end

while size > 0
do
    book = redis.call('LPOP', cacheName)

    authorId = string.match(string.match(book, authorPattern), [["authorId":"([^"]+)]])
    replacedAuthors = string.format(replacedAuthors , authorId)
    book = string.gsub(book, authorPattern, replacedAuthors)

    affectedEntitiesCount = affectedEntitiesCount + 1
    redis.call('RPUSH', cacheName, book)
    size = size - 1
end
return affectedEntitiesCount

本地书籍

本地缓存名称

作者模式 ='"作者":"[^"]*"'

作者 ID

替代作者 ='"作者":["java.util.ArrayList",["%s"]]'

大小= redis 调用('LLEN',cacheName)

如果大小为0,那么

返回-1

结束

当大小> 0 时

书=redis调用('LPOP',cacheName)

作者Id=字符串匹配(字符串匹配(书,作者模式),[["作者Id":"([^"]+)]])

替代作者=字符串格式化(替代作者,作者Id)

书=字符串替换(书,作者模式,替代作者)

受影响的实体计数=受影响的实体计数 + 1

redis调用('RPUSH',cacheName,书)

大小=大小-1

结束

返回受影响的实体计数

2021-03-31 15:27:29
用户3160475
用户3160475

由于您似乎在列表中存储了 JSON 编码的值,您可以使用嵌入在 Redis Lua 引擎中的 cjson

例如:

    ...
    book = cjson.decode(redis.call('LPOP', cacheName))
    book['bookId'] = book['bookId']..'foo' -- 将 'foo' 拼接到 bookId
    ...
    redis.call('RPUSH', cacheName, cjson.encode(book))

注意:还要确保使用 KEYS 输入数组来参数化脚本的输入键名(例如 local cacheName = KEYS[1])。

2021-03-31 16:43:29