How to combine search text with other criteria using Redis?

I have successfully written the intersection of text search and other criteria using Redis. For this, I use a Lua script. The problem is that I not only read, but also write values ​​from this script. From Redis 3.2 this can be achieved by calling redis.replicate_commands(), but not earlier than 3.2.

The following shows how I store the values.

Names

> HSET product:name 'Cool product' 1
> HSET product:name 'Nice product' 2

Price

> ZADD product:price 49.90 1
> ZADD product:price 54.90 2

Then, to get all the products that match 'ice', for example, I call:

> HSCAN product:name 0 MATCH *ice*

However, since it HSCANuses the cursor, I have to call it several times to get all the results. This is where I use the Lua script:

local cursor = 0
local fields = {}
local ids = {}
local key = 'product:name'
local value = '*' .. ARGV[1] .. '*'

repeat
    local result = redis.call('HSCAN', key, cursor, 'MATCH', value)
    cursor = tonumber(result[1])
    fields = result[2]
    for i, id in ipairs(fields) do
        if i % 2 == 0 then
            ids[#ids + 1] = id
        end
    end
until cursor == 0
return ids

script , SADD key EVAL(SHA) .... . , ID script:

if i % 2 == 0 then
    ids[#ids + 1] = id
    redis.call('SADD', KEYS[1], id)
end

redis.replicate_commands() . ID , script (. KEYS[1]).

, , 100 40 50, "", :

> ZUNIONSTORE tmp:price 1 product:price WEIGHTS 1
> ZREMRANGEBYSCORE tmp:price 0 40
> ZREMRANGEBYSCORE tmp:price 50 +INF
> EVALSHA b81c2b... 1 tmp:name ice
> ZINTERSTORE tmp:result tmp:price tmp:name
> ZCOUNT tmp:result -INF +INF
> ZRANGE tmp:result 0 100

ZCOUNT, , , count / 100.

, Redis 3.2. AWS, Redis 2.8, . , HSCAN script script. Redis 2.8?

:

  • , Redis (, ), .
  • Redis , 3.2.
  • ( ) . , .
  • , - . .
+4
2

, , , HSCAN, .

-, SCAN Lua script. - - , , ( ). , HSCAN - , .

, :

:

  • HSCAN . , .

Lua:

  1. Redis 3.2 script .
  2. script, . ( , .)
  3. HSCAN HKEYS script , Lua. HKEYS , . , , , , , . ( HSCAN O (N) .)
+1

, , lua scirpt. , lua, lua ( []). sadd (key, members []). .

> ZUNIONSTORE tmp:price 1 product:price WEIGHTS 1
> ZREVRANGEBYSCORE tmp:price 0 40
> ZREVRANGEBYSCORE tmp:price 50 +INF
> nameSet[] = EVALSHA b81c2b... 1 ice 
> SADD tmp:name nameSet
> ZINTERSTORE tmp:result tmp:price tmp:name
> ZCOUNT tmp:result -INF +INF
> ZRANGE tmp:result 0 100

, . - , , .

,

UPDATE , array ([]) lua, lua . script , , sadd.

String [] nameSet = (String[]) evalsha b81c2b... 1 ice -> This is in java
SADD tmp:name nameSet

lua script , 1-.

local cursor = 0
local fields = {}
local ids = {}
local key = 'product:name'
local value = '*' .. ARGV[1] .. '*'

repeat
    local result = redis.call('HSCAN', key, cursor, 'MATCH', value)
    cursor = tonumber(result[1])
    fields = result[2]
    for i, id in ipairs(fields) do
        if i % 2 == 0 then
            ids[#ids + 1] = id
        end
    end
until cursor == 0
return ids
+2

All Articles