2011-01-30 11 views

Respuesta

12

La única opción que creo es iterar el conjunto ordenado y calcular el lado del cliente de suma.

+0

gracias! Sí, creo que esto es probablemente demasiado específico de una característica para que Redis se moleste en implementar ... esp. ya que puede que ni siquiera esté haciendo algo recomendable. Estoy usando un zset para almacenar los ID de regalo recibidos de un usuario y los ID de usuario de envío y el puntaje es el número de veces que se ha recibido el mismo regalo del mismo remitente. Por ejemplo, 'ZINCR 123: regalos 1" 3 | 345 "' envía el regalo w id 3 del usuario 345 al usuario 123. Por lo tanto, quiero obtener el total de regalos que ha recibido un usuario. ¿Ver? Tal vez hay una mejor manera de implementar esto? Es como Facebook Gift API. ¡Redis gobierna! :) ¡Gracias por todo! – ma11hew28

3

Si los conjuntos son pequeños, y no necesita un rendimiento excelente, simplemente iteraría (zrange/zrangebyscore) y sumaría los valores del lado del cliente.

Si, por otro lado, está hablando de muchos miles: millones de elementos, siempre puede mantener un conjunto de referencia con totales acumulados para cada usuario y aumentarlos/disminuirlos a medida que se envían los regalos.

Así que cuando usted hace su ZINCR 123:gifts 1 "3|345", se podría hacer una orden ZINCR independiente, que podría ser algo como esto:

ZINCR received-gifts 1 <user_id> 

Entonces, para obtener el # de los dones recibidos para un usuario determinado, sólo tiene para ejecutar un Zscore:

ZSCORE received-gifts <user_id> 
+0

El conteo incremental gana de lejos por problemas en línea. El análisis solo debe usarse en algoritmos fuera de línea, en mi humilde opinión, ya que nadie puede predecir el futuro crecimiento de los conjuntos de datos. Esta respuesta debería ser la aceptada. Ah, y btw: uno podría escribir un comando personalizado que hace ambas cosas (agregar a un conjunto e incrementar el contador, actualizar un valor y ajustar el contador, eliminar del conjunto & ...) –

5

Disponible desde Redis v2.6 es la capacidad más impresionante para ejecutar scripts Lua en el servidor Redis. Esto hace que el reto de sumar las puntuaciones de un conjunto ordenado de trivial:

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 

Runtime ejemplo:

~$ 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 
+2

Una nota importante es que el servidor Redis -side lua scripts bloquea TODO, lo que puede ser un obstáculo en la mayoría de los casos. Fuente: http://stackoverflow.com/a/30896608/2440 – Sire

1

Aquí es un pequeño script lua que mantiene la puntuación total zConfigurar a medida que avanza, en un contador con la clave postfijada con '.ss'. Puedes usarlo en lugar de 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) 
+1

Ese script no debe construir la clave dentro de lua ('KEYS [1] .. '. Ss''), que" viola la semántica del comando EVAL como todas las las claves que usa la secuencia de comandos se deben pasar usando la matriz KEYS "- https://redis.io/commands/eval – Jonathan

+0

@Jonathan tiene razón, la clave para la puntuación total también debe aprobarse en las LLAVES [] – Patrick

Cuestiones relacionadas