Is there any way to do an atomic set only if not already set in Redis?
Specifically, I'm creating a user like "myapp:user:user_email" and want Redis to give me back an error if "user_email" is already taken, instead of silently replacing the old value. Something like declare, not replace.
See SETNX
Set key to hold string value if key does not exist. In that case, it is equal to SET. When key already holds a value, no operation is performed. SETNX is short for "SET if N ot e X ists".
You can check the return value. If it is 0, the key was not set, implying it already existed.
Related
I just learned that when a list is empty, EXISTS returns 0.
I am processing a list using this:
rpoplpush source target
When I am done processing, I still want to look at the source to see if it is empty, but also if the key exists. But since the list is empty, it is returning 0.
EXISTS source
(integer) 0
Is there a way to know that your list is empty, but the key does exist still in redis?
In redis, empty list can't exist. If after popping an element list becomes empty, it is deleted.
if (listTypeLength(o) == 0) {
notifyKeyspaceEvent(NOTIFY_GENERIC,"del",
c->argv[1],c->db->id);
dbDelete(c->db,c->argv[1]);
}
My question is this:
How can I use SUBSET (a discontinuous set) to refer to an index location in another set as opposed to an actual value? I see that ord() can be used to return the position of a value in a set, but I want the reverse of this...
my reason for needing this:
I have a model in which some of the set and data statements are roughly:
set ALL_TIME := {0..20000};
param DATA {ALL_TIME}; #read from file in later data statement;
set myTIME := {0...1000};
I am looping over the myTIME set and each time solving the model and then incrementing the start and end by 1: {1..1001}, {2..1002}, {3..1003}, etc.
I have another discontinuous set being read in from a file that looks something like this (yes below is bad syntax, the "...." is just there to mean that the pattern continues until it hits 1000 so I don't have to type it all) :
set SUBSET := {6,7,8,9,10, 16,17,18,19,20, 26,27.....}
Once myTIME increments such that it no longer contains "6", I get a subscript undefined error from a constraint which I understand to be because myTIME in this case is {7..1007} and thus in the following, tSUB=6 causes ALPHA[6] and is undefined:
subject to CONSTRAINT {tSUB in SUBSET}:
ALPHA [tSUB] = ALPHA[last(tSUB)];
What I want is to be able to use SUBSET to always refer to the same index location of ALPHA, DATA, etc.
So:
SUBSET[0] (which equals 6) should always be the 6th value of for example DATA:
{tSUB in SUBSET}: DATA[tSUB]. when tSUB is 0, I want the 6th value of DATA.
(I am new to Ampl and have a hard time wrapping my head around how indexing and sets work - if anything didn't make sense, please ask and I'll try to clarify. If you think it would be more helpful to see my actual code I'll try to sanitize the company data out and post it). Also, some of the code bits above have abysmal syntax. They are not copied from my code, just approximated to try to explain my problem. :)
You can get i-th member of set S with member(i, S), where i is a 1-based index and S is an ordered set. This is described in section 5.6 Ordered sets of the AMPL book.
In Jedis, I want to set some key and value with expiring time by a single invocation.
I can do this by combination of set() and expire() but it needs two invocations.
I found the following method:
set(final String key, final String value, final String nxxx, final String expx, final long time)
But I have to choose nx (Only set the key if it does not already exist.) or xx (Only set the key if it already exist.).
I want to cover both cases.
Any suggestion? Or any reason to be written like this?
Redis has a SETEX command, which sets the key with an expiry.
jedis.setex(key, expireAfter, value);
This question is so misleading. nx and xx are indeed for different use cases and mutually exclusive. If you want to simply overwrite any expiry, simply don't pass in none of below:
NX -- Set the key only when the key doesn't exist
XX -- Set the key only when the key has existed
I'm using jedis, and wish to get the result of a key and modify it and then store it back,
String dataToModify = jedis.get(parent_id);
//some modify eg:
modifiedData = dataToModify + "modify";
jedis.set(parent_id, modifiedData);
but I then realized that if someone else modified data in key parent_id, between this get and set, there will be collision. the watch-multi-exec does not work since I need to get the value of key parent_id during the transaction. Is there any other way to do this atomically? thanks
Not sure regarding the exact jedis syntax, but Redis' WATCH/MULTI/EXEC will let you do that (I.e. run the get/set flow atomically). Alternatively, if you implement your workflow in a server-side Lua script, that would also guarantee atomicity.
How about saving the date in epoch (also known as unix time) value, this way you can treat your date as a number and use INCRBY command e.g.:
jedis.incrby(parent_id, modify);
I tried adding some sample score-value pairs to redis sorted set using below code:
String key = "set";
redis.zadd(key, 5, "1034");
redis.zadd(key, 2, "1030");
redis.zadd(key, 1, "1089");
and tried retrieving it using byteArray and BitSet
byte[] byteArr = redis.get(key.getBytes());
BitSet bitSet = fromByteArrayReverse(byteArr);
System.out.println(bitset.toString()));
also i tried executing
System.out.println(redis.get(key.getBytes()));
which is supposed to give me an address of the byte-array
But for both of these commands i get the error
" ERR Operation against a key holding the wrong kind of value"
So can anyone please tell me why does this error occur in the first place and also the correct redis command/code to retrieve values from a redis sorted-set??
What you want is calling
ZSCORE key "1034"
Or in the case of wanting only elements between two particular scores
ZRANGEBYSCORE key lower upper
Since you also have "rank" (position or index, as in a list) you can also ask for example for the first three elements in your set
ZRANGEBYRANK key 0 2
The error you are getting is because once you assign a value to a key, that value defines the type of the internal structure on redis, and you can only use commands for that particular structure (or generic key commands such as DEL and so on). In your case you are trying to mix sorted sets with byte operations and it doesn't match.
To see all sorted set commands, please refer to http://redis.io/commands#sorted_set