skip to Main Content

I Need a short advise please about LUA script for modification object in Redis.
I Have Redis List with entities like that:

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

now, I need to change my entity to allow multiple authors for certain book, and create migration script for this:

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

What I Think I need to do with LUA:

local book
local cacheName --cache name in my case
local authorId;

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

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

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

But I have no idea how to modify book according requirements.
Can someone take a look and suggest?

2

Answers


  1. Chosen as BEST ANSWER

    solved:

    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
    

  2. Since it appears that you’re storing JSON-encoded values in your list, you can use the cjson library that’s embedded in Redis’ Lua engine.

    For example:

        ...
        book = cjson.decode(redis.call('LPOP', cacheName))
        book['bookId'] = book['bookId']..'foo' -- concat 'foo' to bookId
        ...
        redis.call('RPUSH', cacheName, cjson.encode(book))
    

    Note: also make sure that you use the KEYS input array to parameterize the script’s input key names (e.g. local cacheName = KEYS[1])

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search