Does redis store duplicate values or just a pointer / reference - redis

If two distinct keys have the same value (and say the value is large) does redis store the value twice or will it use a pointer / reference. The way git does ?

Redis stores them as two independent key-value pairs.
If you want to remove the duplication, you have to build an index from multiple keys to a shared value by yourself.

Related

IndexedDB using an index versus a key range?

In indexedDB, if the keys are arrays of integers such as [n,0] through [n,m], for operations that involve getting all the records in which the first element of the array key is n or opening a cursor on the same set of records, is there any advantage to using an index on an additonal property that stores n over using a key range?
Reasons to think an index may not be better include that the browser has to maintain the index for each change to the object store, an additional property has to be added to each record to store already stored data n, and little may be gained since the keys in the index will always point to consecutive records in the object store rather than dispersed throughout.
If the number of different values of n are likely no more than 1,000 and for m no more than 50, is using an index superior to a key range?
Thank you.
I guess the purpose of indexedDB is to have object store locally.
It is not sql that you need to update columns in every object.
since you change the object structure (saying by adding property)
it is true that all the objects in the store must be rewriten as you said...
emm well... another option for you is to update the db with another store
which contain somthing similar to forien key in sql or uniqe key which store the other stored objects extentions... and in it every obj item is also supposed to be same structured.
I think this is the point you start to use onupgradeneeded intansively.

Redis hash vs key hierarchy

What's the practical difference between keeping data in multiple hashes (HSET foo oof 1, HSET bar rab 2) and using plain keys in a hierarchy (SET foo:oof 1, SET bar:rab 2)?
According to the manual, you'd use hashes to represent a single object.
Also, it's not that efficient to iterate over Redis keys, so if you need to get all the data from a single object, HGETALL is your friend, not a KEYS thing:10:*/multiget fiasco.
However, you can't e.g. set expiry for only one key of a hash, so if you need that functionality, you'll want to use regular keys.

Add Version/Flavor to Keys in Redis

We are storing path's to data in redis as following:
KEY: `/pathOfUniqueAsset/v11/`
VALUE: `/disk1/pathOfUniqueAsset/path/v/11/`.
As you can see, the v which stands for version, will grow over time. I was wondering if there is a way to store flavors/versions of a key/value pair?
You can use a Hash instead of a String, as the key's value type. In the Hash, you can have a field per version/flavor and have the value as the associated path.
E.g.:
HSET /pathOfUniqueAsset v11 /disk1/pathOfUniqueAsset/path/v/11/
What are you trying to achieve? Do you need to keep older versions? If not, overwrite the key. If yes, what would 'version' of the key give you? You already know your version from the key. If you arrange your keys as pathOfUniqueAsset.v11, you can later issue KEYS pathOfUniqueAsset.* (or better SCAN) to get all versions. This way you can set EXPIRE individually. If you'll use HSET like #ItamarHaber suggests you can only delete values manually, but iterating a set is much faster than KEYS lookup (EDIT: actually, it depends on some factors, mostly the amount of other keys).
If you instead want a list of assets for each version kept together, you can use dedicated set of all keys associated to this version. Like
SET /pathOfUniqueAsset/v1 ...
HSET assets.v1 pathOfUniqueAsset /pathOfUniqueAsset/v1

Redis: how to use it similar to multi-tables

It seems that Redis has no any entity corresponding to "table" in relational database.
For instance, I have to store:
(token, user_id)
(cart_id, token, [{product_id, count}])
If it doesn't separate store those two, the get method would search from both, which would cause chaos.
By the way, (cart_id, token, [{product_id, count}]) is a shopping cart, how to design such data structure in redis?
It seems that Redis has no any entity corresponding to "table" in relational database.
Right, because it is not a relational database. It is a data structure server which is very different and requires a different approach to be used well.
Ultimately to use Redis in the way it is intended you need to not think in relational terms, but think of the data structures you use in the code. More specifically, how do you need the data when you want to consume it? That will be the most likely way to store it in Redis.
In this case there are a few options, but the hash method works incredibly well for this one so I'll detail it here.
First, create a hash, call it users:to:tokens. Store as the key in the hash the user id, and the value the token. Next create the inverse, a hash called 'tokens:to:users'. You will probably be wanting both of these - the ability to look one up from the other - and this foundation will provide that.
Next, for your carts. This, too, will be a hash: carts:cart_id. In this hash you have the product_id and the count.
Finally up is your third hash token:to:cart which builds an index of tokens to cart id. I'd go a step further and do user:to:cart to be able to pull carts by user as well.
Now as to whether to store the keynote in the map or not, I tend to go with "no". By just storing the ID you can easily build the Redis cart key and not store the key's full path in the data store as well the saving memory usage.
Indeed, if you can do so use integers for all of your IDs. By using integers you can take advantage of Redis' integer storage optimizations to keep memory usage down. Hashes storing integers are quite efficient and very fast.
If needed you can use Redis to build your IDs. You can use the INCR command to build a counter for each data type such as userid:counter, cartid:counter, and tokenid:counter. As INCR returns the new value you make a single call to increment and get the new ID and get cartid:counter will always give you the largest ID if you wanted to quickly see how many carts have been created. Kinda neat , IMO.
Now, where it gets tricky is if you want to use expiration to automatically expire carts as opposed to leaving them to "lie around" until you want to clean things up. By setting an expiration on the cart hash (which has the product,count mapping) your carts will automatically expire. However, their references will still be hanging out in the token:to:cart hash. Removing that is a simple periodic task which treats over the members of token:to:cart and does an exists check on the cart's key. If it doesn't exist delete it from the hash.
Redis is a key-value storage. From redis.io:
Redis is an open source (BSD licensed), in-memory data structure
store, used as database, cache and message broker. It supports data
structures such as strings, hashes, lists, sets, sorted sets with
range queries, bitmaps, hyperloglogs and geospatial indexes with
radius queries.
So if you want to store two diffetent types (tokens and carts) you will need to store two keys for different datatypes. For example:
127.0.0.1:6379> hset tokens.token_id#123 user user123
(integer) 1
127.0.0.1:6379> hget tokens.token_id#123 user
"user123"
Where tokens is a namespace for tokens only. It is stored as Redis-Hash:
Redis Hashes are maps between string fields and string values, so they
are the perfect data type to represent objects
To store lists I would do the following:
127.0.0.1:6379> hmset carts.cart_1 token token_id#123 cart_contents cart_contents_key1
OK
127.0.0.1:6379> hmget carts.cart_1 token cart_contents
1) "token_id#123"
2) "cart_contents_key1" # cart_contents is a list of receipts.
cart_contents are represented as a Redis-List:
127.0.0.1:6379> rpush cart_contents.cart_contents_key1 receipt_key1
(integer) 1
127.0.0.1:6379> lrange cart_contents.cart_contents_key1 0 -1
1) "receipt_key1"
Receipt is Redis-Hash for a tuple (product_id, count):
127.0.0.1:6379> hmset receipts.receipt_key1 product_id 43 count 2
OK
127.0.0.1:6379> hmget receipts.receipt_key1 product_id count
1) "43" # Your final product id.
2) "2"
But do you really need Redis in this case?

Is it possible to do LIST operations on the value of a HASH?

I am still new to Redis and wondering if it would be possible to have a HASH of LIST.
Then I could do for example LPOP HASH myKey where the hash set holds each list's key and the lists contains data that I want to manipulate.
Redis does not provide nested data structures, therefore a List of Hashes isn't possible. A Redis List can only contain strings, but what you could do is store the Hashes' key names in a List and do HGET after popping.