Reputation: 116
The goal is to design a queue with the some values say A. but I have to pick a value from the queue only if incoming value D doesn't matches with B & C.
The relation between A, B and C can be think of as a tabular data.
+------------------+------------------+------------------+
| A | B | C |
+------------------+------------------+------------------+
| 12312 | 123123 | 2323 |
| <some int value> | <some int value> | <some int value> |
+------------------+------------------+------------------+
I have an incoming value D.
Now I have to simply select value A from the row where value of D is not equal to either B or C.
Please note neither of A, B, C are known to in advance. These will be populated by a separate process either in db or redis. The only value I know is D and I have to find the value of A for the first row I find where values B and C are not matching with D.
This is very simple to do if i do this on a relational DB i.e sample query would be
Select A from table where B != D and C != D LIMIT 1
But I am not sure how I can do this using key-value store like redis?
The most basic idea will be to maintain a list in redis in following format
somekey: ['a1:b1:c1', 'a2:b2:c2', 'a3:b3:c3', ...]
then I could simply run lrange somekey 0 -1
and then iterate over every elment, split on :
untill I find an element where b
and c
both are not equal to D
.
But This approach is very expensive, as I have to iterate over entire every list for every value of D.
Another approach I have tried to create redis keys in the following format
+------------------+-----------------------------+
| Key | Value |
+------------------+-----------------------------+
| prefix_<B1>_<C1> | [<A11>, <A12>, <A13>, ....] |
| prefix_<B2>_<C2> | [<A21>, <A22>, <A23>, ....] |
+------------------+-----------------------------+
The problem with this approach is that redis doesn't support the searching for keys not matching a pattern
.
So I have to first get all keys then, do a regex search on application level.
Then once I find a key, i just pop first value from the list at that key.
My preferred approach is to do it using redis, but other solutions are also welcome.
Upvotes: 0
Views: 4099
Reputation: 4502
suppose you store values in the following format:
+--------------+-----------------+
| key | value |
+--------------+-----------------+
| a1:b1:c1 | any value |
+--------------+-----------------+
| a2:b2:c2 | any value |
+--------------+-----------------+
| a3:b3:c3 | any value |
+--------------+-----------------+
| a4:b4:c4 | any value |
+--------------+-----------------+
For any value d
you want all the keys that does not contain d:d as suffix such as whatever:d:d
, here is the following regex that will return all the keys that does not d:d
in suffix.
KEYS *[^d:d]
suppose values of d
is 123
then the pattern will be: *[^123:123]
.
Here are some cases which I've tested in my console:
127.0.0.1:6379> set 123:456:789 one
OK
127.0.0.1:6379> set 123:456:780 two
OK
127.0.0.1:6379> set 123:456:787 two
OK
127.0.0.1:6379> set 123:455:787 two
OK
127.0.0.1:6379> set aaa:bbb:ccc abc
OK
127.0.0.1:6379> set aaa:ddd:ddd abc
OK
127.0.0.1:6379> keys *
1) "123:456:789"
2) "123:456:787"
3) "123:455:787"
4) "aaa:ddd:ddd"
5) "aaa:bbb:ccc"
6) "123:456:780"
127.0.0.1:6379> keys aaa:*[^ddd:ddd]
1) "aaa:bbb:ccc"
127.0.0.1:6379> keys *[^ddd:ddd]
1) "123:456:789"
2) "123:456:787"
3) "123:455:787"
4) "aaa:bbb:ccc"
5) "123:456:780"
see command keys *[^ddd:ddd]
returning all the keys which does not matched with our expected key.
1) "123:456:789"
2) "123:456:787"
3) "123:455:787"
4) "aaa:bbb:ccc"
5) "123:456:780"
for more check this link: REDIS KEYS
You can also use REDIS SCAN command to fetch not matching keys:
scan 0 MATCH *[^d:d] count 1000
Upvotes: 2