Esempio n. 1
0
def redis_test():
    rj = Client(host='localhost', port=6379)

    # Set the key `obj` to some object
    obj = {
        'answer': 42,
        'arr': [None, True, 3.14],
        'truth': {
            'coord': 'out there'
        }
    }
    rj.jsonset('obj', Path.rootPath(), obj)

    # Get something
    print ('Is there anybody... {}?'.format(
        rj.jsonget('obj', Path('.truth.coord'))
    ))

    # Delete something (or perhaps nothing), append something and pop it
    rj.jsondel('obj', Path('.arr[0]'))
    rj.jsonarrappend('obj', Path('.arr'), 'something')
    print ('{} popped!'.format(rj.jsonarrpop('obj', Path('.arr'))))

    # Update something else
    rj.jsonset('obj', Path('.answer'), 2.17)

    # And use just like the regular redis-py client
    jp = rj.pipeline()
    jp.set('foo', 'bar')
    jp.jsonset('baz', Path.rootPath(), 'qaz')
    jp.execute()
Esempio n. 2
0
    def testUsageExampleShouldSucceed(self):
        "Test the usage example"

        # Create a new rejson-py client
        rj = Client(host='localhost', port=port, decode_responses=True)

        # Set the key `obj` to some object
        obj = {
            'answer': 42,
            'arr': [None, True, 3.14],
            'truth': {
                'coord': 'out there'
            }
        }
        rj.jsonset('obj', Path.rootPath(), obj)

        # Get something
        rv = rj.jsonget('obj', Path('.truth.coord'))
        self.assertEqual(obj['truth']['coord'], rv)

        # Delete something (or perhaps nothing), append something and pop it
        value = "something"
        rj.jsondel('obj', Path('.arr[0]'))
        rj.jsonarrappend('obj', Path('.arr'), value)
        rv = rj.jsonarrpop('obj', Path('.arr'))
        self.assertEqual(value, rv)

        # Update something else
        value = 2.17
        rj.jsonset('obj', Path('.answer'), value)
        rv = rj.jsonget('obj', Path('.answer'))
        self.assertEqual(value, rv)

        # And use just like the regular redis-py client
        jp = rj.pipeline()
        jp.set('foo', 'bar')
        jp.jsonset('baz', Path.rootPath(), 'qaz')
        jp.execute()
        rv1 = rj.get('foo')
        self.assertEqual('bar', rv1)
        rv2 = rj.jsonget('baz')
        self.assertEqual('qaz', rv2)
class ReJson:
    """Facade for ReJson"""
    def __init__(self, host: str, port: Union[str, int]) -> None:
        """Instantiate a connection to ReJson.

        :param host: The hostname/ip of the Redis instance.
        :type host: str
        :param port: The port of the Redis instance.
        :type port: int
        """
        self._client = Client(host=host, port=port, decode_responses=True)

    def keys(self) -> Json:
        """Get all keys"""
        return self._client.keys()

    def post(self, key: str, obj: Json) -> None:
        """Post a new Json object to the store.

        :param key: The key to store the Json at.
        :type key: str
        :param obj: What to store.
        :type obj: Json
        """
        self._client.jsonset(key, Path.rootPath(), obj)

    def get(self, key: str) -> Json:
        """[summary]

        :param key: The key that the Json object was stored at.
        :type key: str
        :return: The Json stored at `key`.
        :rtype: Json
        """
        return self._client.jsonget(key, Path.rootPath())

    def update(self, key: str, path: str, value: Json) -> None:
        """[summary]

        :param key: The key that the Json object was stored at.
        :type key: str
        :param path: A period seperated string of keys to traverse the Json.
        :type path: str
        :param value: The new value.
        :type value: Json
        """
        self._client.jsonset(key, Path(f".{path}"), value)

    def append(self, key: str, path: str, *values: Json) -> None:
        """Append to some array within a Json obejct.

        :param key: The key that the Json object was stored at.
        :type key: str
        :param path: A period seperated string of keys to traverse the Json.
        :type path: str
        """
        self._client.jsonarrappend(key, Path(f".{path}"), *values)

    def pop(self, key: str, path: str) -> Json:
        """Pop from from array within a Json object.

        :param key: The key that the Json object was stored at.
        :type key: str
        :param path: A period seperated string of keys to traverse the Json.
        :type path: str
        :return: The Json value popped from the array.
        :rtype: Json
        """
        return self._client.jsonarrpop(key, f".{path}")

    def remove(self, key: str, path: str, value: Json) -> None:
        """Remove something from some array within a Json object.
        
        :param key: The key that the Json object was stored at.
        :type key: str
        :param path: A period seperated string of keys to travers the Json.
        :type path: str
        :param value: The value to remove from the array.
        :type value: Json
        """
        index = self._client.jsonarrindex(key, f".{path}", value)
        self._client.jsondel(key, f"{path}[{index}]")
Esempio n. 4
0
class RedisJson:
    def __init__(self):
        self._rjson = Client(host='localhost',
                             port=6379,
                             decode_responses=True)
        self._root_path = Path.rootPath()

    '''
        Insert JSON into db

        Structure of JSON to insert:
        {
            'lat'  : 80.844,
            'long' : -43.139,
            'resources' : {
                'mask' : 450,
                'vaccine' : 56,
                'oxygen' : 800,
                ...
            },
            'updated' : <unix time ms>
        }
    '''

    def insert(self, key, data):
        self._rjson.jsonset(key, self._root_path, data)

    '''
        Return list of all JSON objects stored in db

        TODO: added this for now, but loading everything in memory doesn't seem
        like a great idea, maybe RedisSearch will help with this. Or maybe make
        this return a generator which can be iterated through
    '''

    def get(self):
        results = []
        for key in self._rjson.scan_iter():
            results.append(self._rjson.jsonget(key, self._root_path))

        return results

    '''
        Update field of a JSON object in db

        Syntax for `path` argument:
        E.g. we have {
            'key1' : value1,
            'key2' : {
                'key3' : value2
            }
        }

        To update value2, `path` should be ".key2.key3"
    '''

    def update(self, key, path, new_value):
        self._rjson.jsonset(key, path, new_value)

    '''
        Delete a JSON value from the db
    '''

    def delete(self, key):
        self._rjson.jsondel(key, self._root_path)
Esempio n. 5
0
    'arr': [None, True, 3.14],
    'truth': {
        'coord': 'out there'
    }
}

jsondata = json.dumps(obj)

rj.jsonset('obj', Path('A2AA'), obj)

# Get something
temp = rj.jsonget('obj', Path('A2AA.truth.coord'))

print (f'Is there anybody... {temp}?')

# Delete something (or perhaps nothing), append something and pop it
rj.jsondel('obj', Path('.arr[0]'))
rj.jsonarrappend('obj', Path('.arr'), 'something')
popped = rj.jsonarrpop('obj', Path('.arr'))
print(f'{popped} popped!')

# Update something else
rj.jsonset('obj', Path('.answer'), 2.17)

# And use just like the regular redis-py client
jp = rj.pipeline()
jp.set('foo', 'bar')
jp.jsonset('baz', Path.rootPath(), 'qaz')
jp.execute()

Esempio n. 6
0
class RejsonDb(KeyValueStorage):
    def __init__(self, conf):
        """
        arguments:
        conf -- a dictionary containing 'settings' module compatible configuration of the plug-in
        """
        self._host = conf['host']
        self._port = int(conf['port'])
        self._db = int(conf['id'])
        self.redis = Client(host=self._host,
                            port=self._port,
                            db=self._db,
                            decode_responses=True)
        self._scan_chunk_size = 50

        try:
            self.redis.jsonget('-')
        except ResponseError as e:
            if 'unknown command' in str(e):
                logging.fatal(
                    "Rejson DB Plug-in requires Redis with RedisJSON module enabled"
                )
            else:
                raise e

    def rename(self, key, new_key):
        return self.redis.rename(key, new_key)

    def list_get(self, key, from_idx=0, to_idx=-1):
        """
        Returns a stored list. If there is a non-list value stored with the passed key
        then TypeError is raised.

        arguments:
        key -- data access key
        from_idx -- optional start index
        to_idx -- optional (default is -1) end index (including, i.e. unlike Python);
        negative values are supported (-1 = last, -2 = penultimate,...)
        """
        data = self.get(key, [])
        if isinstance(data, list):
            if to_idx == -1:
                return data[from_idx:]
            return data[from_idx:to_idx + 1]
        raise TypeError('Object is not a list')

    def list_append(self, key, value):
        """
        Add a value at the end of a list

        arguments:
        key -- data access key
        value -- value to be pushed
        """
        if not self.exists(key):
            self.set(key, [])
        self.redis.jsonarrappend(key, Path.rootPath(), value)

    def list_pop(self, key):
        """
        Removes and returns the first element of the list stored at key.

        arguments:
        key -- list access key
        """
        return self.redis.jsonarrpop(key)

    def list_len(self, key):
        """
        Returns length of a list. If there is a non-list value stored with the passed key
        then TypeError is raised.

        arguments:
        key -- data access key
        """
        if not self.exists(key):
            return 0
        return self.redis.jsonarrlen(key)

    def list_set(self, key, idx, value):
        """
        Sets the list element at index to value

        arguments:
        key -- list access key
        idx -- a zero based index where the set should be performed
        value -- a JSON-serializable value to be inserted
        """
        # TODO the operation pair should be atomic to avoid possible race conditions
        self.redis.jsonarrpop(key, Path.rootPath(), idx)
        return self.redis.jsonarrinsert(key, Path.rootPath(), idx, value)

    def list_trim(self, key, keep_left, keep_right):
        """
        Trims the list from the beginning to keep_left - 1 and from keep_right to the end.
        The function does not return anything.

        arguments:
        key -- data access key
        keep_left -- the first value to be kept
        keep_right -- the last value to be kept
        """
        self.redis.jsonarrtrim(key, Path.rootPath(), keep_left, keep_right)

    def hash_get(self, key, field):
        """
        Gets a value from a hash table stored under the passed key

        arguments:
        key -- data access key
        field -- hash table entry key
        """
        if self.redis.jsontype(key, Path(f'["{field}"]')) is None:
            return None
        return self.redis.jsonget(key, Path(f'["{field}"]'), no_escape=True)

    def hash_set(self, key, field, value):
        """
        Puts a value into a hash table stored under the passed key

        arguments:
        key -- data access key
        field -- hash table entry key
        value -- a value to be stored
        """
        if not self.exists(key):
            self.set(key, {})
        self.redis.jsonset(key, Path(f'["{field}"]'), value)

    def hash_del(self, key, field):
        """
        Removes a field from a hash item

        arguments:
        key -- hash item access key
        field -- the field to be deleted
        """
        self.redis.jsondel(key, Path(f'["{field}"]'))

    def hash_get_all(self, key):
        """
        Returns a complete hash object (= Python dict) stored under the passed
        key. If the provided key is not present then an empty dict is returned.

        arguments:
        key -- data access key
        """
        return self.get(key)

    def get(self, key, default=None):
        """
        Gets a value stored with passed key and returns its JSON decoded form.

        arguments:
        key -- data access key
        default -- a value to be returned in case there is no such key
        """
        data = self.redis.jsonget(key, Path.rootPath(), no_escape=True)
        if data is None:
            return default
        return data

    def set(self, key, data):
        """
        Saves 'data' with 'key'.

        arguments:
        key -- an access key
        data -- a dictionary containing data to be saved
        """
        self.redis.jsonset(key, Path.rootPath(), data)

    def set_ttl(self, key, ttl):
        """
        Set auto expiration timeout in seconds.

        arguments:
        key -- data access key
        ttl -- number of seconds to wait before the value is removed
        (please note that update actions reset the timer to zero)
        """
        self.redis.expire(key, ttl)

    def get_ttl(self, key):
        return self.redis.ttl(key)

    def clear_ttl(self, key):
        self.redis.persist(key)

    def remove(self, key):
        """
        Removes a value specified by a key

        arguments:
        key -- key of the data to be removed
        """
        self.redis.jsondel(key)

    def exists(self, key):
        """
        Tests whether there is a value with the specified key

        arguments:
        key -- the key to be tested

        returns:
        boolean value
        """
        return self.redis.exists(key)

    def setnx(self, key, value):
        """
        An atomic operation "set if not exists".

        returns:
        1 if the key was set
        0 if the key was not set
        """
        return self.redis.jsonset(key, Path.rootPath(), value, nx=True)

    def getset(self, key, value):
        """
        An atomic operation which obtains current key first and then
        sets a new value under that key

        returns:
        previous key if any or None
        """
        data = self.get(key)
        self.set(key, value)
        return data

    def incr(self, key, amount=1):
        """
        Increments the value of 'key' by 'amount'.  If no key exists,
        the value will be initialized as 'amount'
        """
        if not self.exists(key):
            self.set(key, 0)
        return self.redis.jsonnumincrby(key, Path.rootPath(), amount)

    def hash_set_map(self, key, mapping):
        """
        Set key to value within hash 'name' for each corresponding
        key and value from the 'mapping' dict.
        Before setting, the values are json-serialized
        """
        return self.set(key, mapping)