Domanda

Qual è il modo migliore per ottenere la somma dei PUNTEGGI in un insieme ordinato di Redis?

È stato utile?

Soluzione

L'unica opzione che penso sia l'iterazione dell'insieme ordinato e il calcolo della somma lato client.

Altri suggerimenti

Disponibile a partire da Redis v2.6 è la capacità più straordinaria di eseguire script Lua sul server Redis.Questo rende banale la sfida di riassumere i punteggi di un Sorted Set:

local sum=0
local z=redis.call('ZRANGE', KEYS[1], 0, -1, 'WITHSCORES')

for i=2, #z, 2 do 
    sum=sum+z[i]
end

return sum

Esempio di runtime:

~$ redis-cli zadd z 1 a 2 b 3 c 4 d 5 e
(integer) 5
~$ redis-cli eval "local sum=0 local z=redis.call('ZRANGE', KEYS[1], 0, -1, 'WITHSCORES') for i=2, #z, 2 do sum=sum+z[i] end return sum" 1 z
(integer) 15

Se i set sono piccoli e non hai bisogno di prestazioni killer, io itererei semplicemente (zrange / zrangebyscore) e sommerei i valori lato client.

Se, d'altra parte, stai parlando di molte migliaia, milioni di articoli, puoi sempre mantenere un set di riferimenti con totali parziali per ogni utente e incrementarli / decrementarli man mano che i regali vengono inviati.

Quindi, quando esegui il tuo ZINCR 123:gifts 1 "3|345", potresti eseguire un comando ZINCR separato, che potrebbe essere qualcosa del genere:

ZINCR received-gifts 1 <user_id>

Quindi, per ottenere il numero di regali ricevuti per un determinato utente, è sufficiente eseguire uno ZSCORE:

ZSCORE received-gifts <user_id>

Ecco un piccolo script lua che mantiene il totale del punteggio zset mentre procedi, in un contatore con la chiave postfissa con ".ss".Puoi usarlo al posto di ZADD.

local delta = 0
for i=1,#ARGV,2 do
    local oldScore = redis.call('zscore', KEYS[1], ARGV[i+1])
    if oldScore == false then
        oldScore = 0
    end
    delta = delta - oldScore + ARGV[i]
end
local val = redis.call('zadd', KEYS[1], unpack(ARGV))
redis.call('INCRBY', KEYS[1]..'.ss', delta)
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top