I'm crash coursing right now in redis, using 'the little redis book'.
What's not clear to me is how I can autogenerate key values.
So for example, the book uses this set statement:
set users:9001 '{"id":9001, "email":"leto#dune.gov"}'
How can i set things up so that the system keeps track of the next available id? In this case... 9002?
I know there is a INCR function... But I don't know how to incorporate both of these functions together.
So for example, let's say i do this using the redis-cli:
set mykey 1
set users:mykey '{"id":mykey, "email":"leto#dune.gov"}'
This works on the command line, but I need a way to do this programmatically. I'm thinking I would:
get mykey
INCR mykey
set users:mykey ....
Does this seem right? is there another way to do this? Also how do I programmatically using phpredis?
Thanks.
Yes, that is the right way to do it. But a small change in your approach,
When you do INCR you will get a incremented value returned by redis. you can use it directly in the next command. So it is simply,
var counter = INCR key
set users:counter . . .
So here you start from the index 1. ie, users:1, users:2 and so on.
Hope this is clear.
Related
Using sort one can sort a set and get external keys using results from the sort component of query.
By way of example:
If the external key/value are defined as various keys using the pattern:itemkey:<somestring>
And a sorted list has list of the members then issuing command sort <lists key> by nosort get itemkey:* would get the values of the referenced keys.
I would like to be able to sort through a sorted list and delete these individual keys but it appears that sort <key> by nosort del itemkey:* is not supported.
Any suggestions on how to get list of values stored in a set and then delete the external keys?
Obviously I can do this with two commands, first getting the list of values and then by iterating through list call the delete function - but this is not desirable as I requite atomic operation.
To ensure atomic operation one can use either transactions or redis' lua scripts. For efficiency I decided to go with using script. This way the entire script is completed before next redis action/request is processed.
In code snippet below. I used loadScript in order to store script redis side reducing traffic with every call, the response from loadScript is then used as identifier to Jedis's evalsha command.
Using Scala (Note Jedis is a Java library, hence the .asJava):
val scriptClearIndexRecipe = """local names = redis.call('SORT', KEYS[1]);
| for i, k in ipairs(names) do
| redis.call('DEL', "index:recipe:"..k)
| end;
| redis.call('DEL', KEYS[1]);
| return 0;""".stripMargin
def loadScript(script: String): String = client.scriptLoad(script)
def eval(luaSHA: String, keys: List[String], args: List[String]): AnyRef = {
client.evalsha(luaSHA, keys.asJava, args.asJava)
}
I'm new to Redis...
Can I remove a member from a sorted set if the member's score has not changed?
Note: I know that I can do the following:
WATCH my-set
... [do some other stuff] ...
MULTI
ZREM my-set my-member
EXEC
But I believe this will abort the transaction (i.e. not execute ZREM) if any member of the set has changed. I'm only interested in aborting the transaction if my-member score has changed.
Can I achieve this without using server-side Lua?
Thanks!
I'm iterating through data and dumping some to a Redis DB. Here's an example:
hmset id:1 username "bsmith1" department "accounting"
How can I increment the unique ID on the fly and then use that during the next hmset command? This seems like an obvious ask but I can't quite find the answer.
Use another key, a String, for storing the last ID. Before calling HMSET, call INCR on that key to obtain the next ID. Wrap the two commands in a MULTI/EXEC block or a Lua script to ensure the atomicity of the transaction.
Like Itamar mentions you can store your index/counter in a separate key. In this example I've chosen the name index for that key.
Python 3
KEY_INDEX = 'index'
r = redis.from_url(host)
def store_user(user):
r.incr(KEY_INDEX, 1) # If key doesn't exist it will get created
index = r.get(KEY_INDEX).decode('utf-8') # Decode from byte to string
int_index = int(index) # Convert from string to int
result = r.set('user::%d' % int_index, user)
...
Note that user::<index> is an arbitrary key chosen by me. You can use whatever you want.
If you have multiple machines writing to the same DB you probably want to use pipelines.
I was looking at another question in stackoverflow regarding auto increment fields in orientdb, where one of the answers was to create our own vertex with counter field.
However, when I'm trying to execute the following code (both java api and console script batch), It is not working.
Do note however that the id is returned good (did some debug attempts, returning the id variable only), and the vertex is created.
However, the vertex id is always null (unless I set it explicit, that is).
The script:
script sql
LET id = UPDATE CCounter INCREMENT value=1 RETURN AFTER $current WHERE name='session'
LET csession = CREATE VERTEX CDate SET id=$id.result, meet_date='2015-01-01 15:23:00'
end
I tried playing around with $id and $current , but nothing seems to work.
Currently I am doing it in a 2-transaction mode; one to get the id, and another to create the vertex. I really hope there is a better way though.
P.S.
I am using version 2.0-M2
You should execute
LET csession = CREATE VERTEX CDate SET id=$id.value, meet_date='2015-01-01 15:23:00'
Note the $id.value in place of $id.result.
As stated in a comment to Lvca, the answer was:
(1) Change the field name. Id seems to be reserved (ish). It's probably possible to still bypass it and use a field named 'id', but I didn't want to mess around with it.
(2) From some reason, the result was a collection (shown as '[id]'). It took me some time to figure it out, but I just had to choose the first value from it.
(3) Also, there are 2 'values' here. One of the field ($current.value), and the second one(not sure where it's coming from).
Final solution that works:
script sql
LET id = UPDATE CCounter INCREMENT value = 1 RETURN AFTER $current.value WHERE name='session'
LET csession = CREATE VERTEX CDate SET data_id=$id[0].value, meet_date='2015-01-01 15:23:00'
end
I have a Redis 2.8.3 service where I am storing data in sets (created with SADD) such as:
Customers (set)
.....Custname (set)
.........application (set)
..............time (set)
...................detail (hash)
Once each detail hash has been processed, it is removed using SREM and then if the parent set (time and application) is found empty using SCARD, it is removed using SREM.
Although this is working, it appears to be leaving the keys for each removed item. So there
are keys such as 'Customer:Custname:application:time' left lying around.
What is the most efficient way to remove the set members and remove the corresponding key at the same time?
The solution with LUA procedure would be best choise. The pseudocode looks like
if 1 == srem(key, value) then
if 0 == scard(key) then
del(key)
end if
end if