Search code examples
jsonredisnode-redisredisjsonredislabs

Manipulating nested array of obects in RedisJSON


I have a JSON with nested array like below to be saved in Redis. I am using RedisJSON module to save the data as JSON.

customer:12345 : {
    info : {
        key1: val1,
        key2: val2,
        key3: val3
    },
    rides: [
        {
            rideid: xxx,
            from: fromval,
            to: toval,
            date: dateofride,
            distance: distanceval,
            points: pointsval
        },
        {
            rideid: yyy,
            from: fromval,
            to: toval,
            date: dateofride,
            distance: distanceval,
            points: pointsval
        },
        ...
    ]
}

I have a case where a new item can be added to the array or the existing one can be edited. I am using node-redis client with express.js. Express app receives only the data which is changed or added in rides array. If the item is already in the array, new data has to replace the existing array item (rideid is the key of each object), else it has to be added to the array. How do I achieve this?


Solution

  • Given the following JSON document

    {
        "info": {
            "key1": "val1"
        },
        "rides": [{
                "rideid": "xxx",
                "points": 0
            },
            {
                "rideid": "yyy",
                "points": 10
            }
        ]
    }
    

    Which is held by the key customer:12345 in RedisJSON with the following command

    127.0.0.1:6379> JSON.SET customer:12345 . "{\"info\": {\"key1\": \"val1\",\"key2\": \"val2\",\"key3\": \"val3\"},\"rides\":[{\"rideid\": \"xxx\",\"points\": 0 },\t{\"rideid\": \"yyy\",\"points\": 10}]}"
    

    You can update ride with rideid yyy by e.g. incrementing the score by 5 as follows

    127.0.0.1:6379> JSON.NUMINCRBY customer:12345 "$.rides[?(@.rideid=='yyy')].points" 5
    "[15]"
    

    $.rides[?(@.rideid=='yyy')].points is a JSONPath expression (more here and here and also answered here)

    To add a new ride

    127.0.0.1:6379> JSON.ARRAPPEND customer:12345 $.rides "{\"rideid\": \"zzz\",\"points\": 5 }"
    1) (integer) 3
    
    

    All RedisJSON commands can be found here