How to use Redisearch from Redis-cli to find an exact number? - redis

I have a set of data like this :
127.0.0.1:6379> json.set a:1 . '{"name":"chloe", "age":26}'
OK
127.0.0.1:6379> json.set a:2 . '{"name":"shan", "age":38}'
OK
127.0.0.1:6379> json.set a:3 . '{"name":"wala", "age":14}'
OK
127.0.0.1:6379> json.set a:4 . '{"name":"Aida", "age":18}'
and I wish to find the one with the age of 14 with the following command and yet I fail.
ft.search idx "#age:(14)"
How can I find the data with exact age of 14?

Try numeric range in following way:
ft.search idx "#age:[14 14]"

Related

How to clear the key in the specified list in Redis?

Redis has the following data:
key value
code1 num1
code2 num2
...
code6000000 num6000000
I have a known fixed list which is not regular:
{code1, code3, code11, ..., code1234567}
How should I design Redis so that I can easily delete these kv?
Redis has a data structure like hash table this.
you can easily follow instructions there to accomplish your needs.
Example:
redis:6379> HSET myhash field1 "Hello"
(integer) 1
redis:6379> HGET myhash field1
"Hello"
redis:6379> HDEL myhash field1
(integer) 1
if you want to delete some keys that are stored in a Redis list, you can use this one line shell script in Linux:
> redis-cli LRANGE mylist 0 -1 | xargs redis-cli DEL

Redis - Sort and filter hash store using string attribute

I have a redis hash store that looks like Item:<id>, with attribute name. I want to filter the hash store by a prefix for name attribute.
What I'm trying to do is store the name (lowercased) in a separate Z-set called Item:::name while setting the score to 0. By doing this, I'm successfully able to get the desired result using ZRANGEBYLEX however I'm unable to map the results back to the original Items. How should I go about implementing something like this?
I've seen multiple autocomplete examples for Redis which require the same functionality but without linking the words back to an actual Item (hash in this case)
In sorted sets the member can't be duplicated, it has to be unique. So different users with the same name will cause problem.
My suggestion requires application layer coding to parse response array and executing hash commands (it will be like secondary indexes);
127.0.0.1:6379> HSET user:1 name jack
(integer) 1
127.0.0.1:6379> HSET user:2 name john
(integer) 1
127.0.0.1:6379> HSET user:3 name keanu
(integer) 1
127.0.0.1:6379> HSET user:4 name jack
(integer) 1
127.0.0.1:6379> ZADD item:names 0 jack::user:1 0 john::user:2 0 keanu::user:3 0 jack::user:4
(integer) 4
127.0.0.1:6379> ZRANGE item:names 0 -1 WITHSCORES
1) "jack::user:1"
2) "0"
3) "jack::user:4"
4) "0"
5) "john::user:2"
6) "0"
7) "keanu::user:3"
8) "0"
127.0.0.1:6379> ZRANGEBYLEX item:names [jack [jo
1) "jack::user:1"
2) "jack::user:4"
At the end you will have name::hash-key formatted array elements. At application layer if you separate each element to two substrings by using ::(any other string such as !!! or || etc) you will have user:1 and user:4.
127.0.0.1:6379> HGETALL user:1
1) "name"
2) "jack"
127.0.0.1:6379> HGETALL user:4
1) "name"
2) "jack"
127.0.0.1:6379>

How may I get the ceiling score (score and member) from a SortedSet in Redis?

In Redis, I want to get the ceiling score (and member) for a score that is not in the SortedSet.
In Java, there is NavigableSet and we may use E ceiling(E e) in order to return the least element in this set greater than or equal to the given element, or null if there is no such element.
Is there any way to do the same in Redis, maybe using SortedSets or other data structure?
Thanks
You can use ZRANGEBYSCORE with a Lua script. Imagine the following sorted set:
zadd test 1 a
zadd test 2 b
zadd test 4 c
You have 3 elements with scores 1, 2, 4 and you'd like to call ceiling(3). Save the following Lua script as script.lua:
local key = KEYS[1]
local givenScore = tonumber(ARGV[1])
local scores = redis.call("ZRANGEBYSCORE", key, givenScore, "+inf", "withscores", "limit", 0, 1)
if (scores == nil or #scores<2) then
return nil
end
return tonumber(scores[2])
and call it with:
$ redis-cli eval "$(cat script.lua)" 1 test 3
Here are some sample runs with the above data set:
$ redis-cli eval "$(cat script.lua)" 1 test 2
(integer) 2
$ redis-cli eval "$(cat script.lua)" 1 test 3
(integer) 4
$ redis-cli eval "$(cat script.lua)" 1 test 4
(nil)

Sorted set of a fixed size in Redis?

I'm a rookie in using Redis, and recently have a problem when I'm thinking the solution to handle the case of high concurrency in out system, I want to use Redis, everybody know access from In-Memory is great faster than IO. Redis sorted set is the possible tool for use to do it, we want to a fixed size of sorted set to contain the user's mobile number, I Googled/Baidued a lot, didn't find any meaning message, so can anybody tell me How to specify Redis Sorted Set a fixed size? And set should tell me any add operation to sorted set is success or not?
Thanks
I don't think you can specify a size, that you will have to check it yourself.
You can use ZCARD
ZCARD KEY
Or you could just remove the first element ZREMRANGEBYRANK
[ZREMRANGEBYRANK][2] [KEY] 0 -[YOURSIZE]
This can be done with a lua script by checking the set size (ZCARD) before adding the element (ZADD). Complexity is O(log(|setsize|)) :
-- KEYS[1] the sorted set
-- ARGV[1] the score
-- ARGV[2] the member
-- ARGV[3] the max size of the sorted set
-- Returns number of elements added
--
if redis.call('ZCARD', KEYS[1]) < tonumber(ARGV[3]) then
return redis.call('ZADD', KEYS[1], ARGV[1], ARGV[2])
else
return 0
end
You can try it out if you save the above snippet as test.lua file and then run it a few times, e.g
redis-cli --eval test.lua myset , 1 A 3
redis-cli --eval test.lua myset , 2 B 3
redis-cli --eval test.lua myset , 3 C 3
redis-cli --eval test.lua myset , 4 D 3
redis-cli --eval test.lua myset , 5 E 3
Verify
127.0.0.1:6379> ZRANGE myset 0 100
1) "A"
2) "B"
3) "C"

Is there MGET analog for Redis hashes?

I'm planning to start using hashes insead of regular keys. But I can't find any information about multi get for hash-keys in Redis wiki. Is this kind of command is supported by Redis?
Thank you.
You can query hashes or any keys in pipeline, i.e. in one request to your redis instance. Actual implementation depends on your client, but with redis-py it'd look like this:
pipe = conn.pipeline()
pipe.hgetall('foo')
pipe.hgetall('bar')
pipe.hgetall('zar')
hash1, hash2, hash3 = pipe.execute()
Client will issue one request with 3 commands. This is the same technique that is used to add multiple values to a set at once.
Read more at http://redis.io/topics/pipelining
No MHGETALL but you can Lua it:
local r = {}
for _, v in pairs(KEYS) do
r[#r+1] = redis.call('HGETALL', v)
end
return r
If SORT let you use multiple GETs with the -> syntax, and all your hashes had the same fields, you could get them in a bulk reply by putting their names into a set and sorting that.
SORT names_of_hashes GET *->field1 *->field2 *->field3 *->etc
But it doesn't look like you can do that with the hash access. Plus you'd have to turn the return list back into hashes yourself.
UPDATE: Redis seems to let you fetch multiple fields if you name your hashes nicely:
redis> hset hash:1 name fish
(integer) 1
redis> hset hash:2 name donkey
(integer) 1
redis> hset hash:3 name horse
(integer) 1
redis> hset hash:1 type fish
(integer) 1
redis> hset hash:2 type mammal
(integer) 1
redis> hset hash:3 type mammal
(integer) 1
redis> sadd animals 1
(integer) 1
redis> sadd animals 2
(integer) 1
redis> sadd animals 3
(integer) 1
redis> sort animals get # get hash:*->name get hash:*->type
1. "1"
2. "fish"
3. "fish"
4. "2"
5. "donkey"
6. "mammal"
7. "3"
8. "horse"
9. "mammal"
There is no command to do it on one shot, but there is a way to do it "nicely", using a list (or sorted set) where you would store you hashKeys, and then retrieve them as bulk using multi.
In PHP:
$redis->zAdd("myHashzSet", 1, "myHashKey:1");
$redis->zAdd("myHashzSet", 2, "myHashKey:2");
$redis->zAdd("myHashzSet", 3, "myHashKey:3");
$members = $redis->zRange("myHashzSet", 0, -1);
$redis->multi();
foreach($members as $hashKey) {
$redis->hGetAll($hashKey);
}
$results = $redis->exec();
I recommand using a sorted set, where you use the score as an ID for your hash, it allows to take advantages of all score based command.
Redis has a HMGET command, which returns the values of several hash keys with one command.