Node-redis: Serialización de valores nulos en un hash

Creado en 13 jun. 2013  ·  19Comentarios  ·  Fuente: NodeRedis/node-redis

cuando el valor de la clave que se establece a través de hset es nulo, se serializa como cadena "nulo". Cuando el hash se recupera a través de hgetall, el valor correspondiente en el objeto devuelto es la cadena "nulo" en lugar de nulo.

Feature Request v4

Comentario más útil

Me di cuenta de que node-redis no realiza ninguna conversión de tipo de datos para los valores de cadena recuperados de redis. Había asumido implícitamente que los valores booleanos, números, etc. se convertirían automáticamente en el tipo de JavaScript correspondiente. Si no considera que esto esté dentro del alcance del proyecto, cierre el problema.

Sin embargo, será bueno tener la conversión automática. Acabo de pasar una cantidad significativa de tiempo depurando un error que surge debido a que un valor falso se recupera como "falso" y pasa por las condiciones de verificación de la verdad de JavaScript.

Todos 19 comentarios

Me di cuenta de que node-redis no realiza ninguna conversión de tipo de datos para los valores de cadena recuperados de redis. Había asumido implícitamente que los valores booleanos, números, etc. se convertirían automáticamente en el tipo de JavaScript correspondiente. Si no considera que esto esté dentro del alcance del proyecto, cierre el problema.

Sin embargo, será bueno tener la conversión automática. Acabo de pasar una cantidad significativa de tiempo depurando un error que surge debido a que un valor falso se recupera como "falso" y pasa por las condiciones de verificación de la verdad de JavaScript.

Correcto, el verdadero / falso es el que me atrapa a mí también.

De hecho, me gustaría abordar esto en la biblioteca, aunque definitivamente hay problemas de rendimiento.

@brycebaril podríamos introducir una bandera en JSON.stringify / parse the input. Esa debería ser una buena solución, ¿no te parece?

Quizás pueda haber una opción en el constructor createClient. Algo como...
_parse_bool_: convierte "verdadero" en verdadero, "falso" en falso
_parse_null_: convierte "nulo" en nulo

Pero entonces, ¿cómo lidiaría con el valor de cadena real de "verdadero" y "nulo"? No hay forma de detectar cuál era el tipo de entrada original.

@Azmisov como @dirkbonhomme señaló que esta no sería una buena solución. Por lo tanto, solo usar JSON.stringify / parse podría ser una opción.

Me gustaría resolver esto no en una base de comando específica sino para todos los comandos. De esa manera tampoco hay penalización de rendimiento, ya que verificamos todos los argumentos de todos modos y, lo que es más importante, se resuelve para cualquier comando sin importar cómo pase los argumentos (matriz, objeto, argumentos).

Prefiero devolver un error si algún comando contiene un valor nulo o indefinido. Esto casi siempre es una señal de que algo anda mal con los argumentos pasados.
Sin embargo, es posible que algunas personas quieran tener una forma diferente de manejar valores nulos o indefinidos, por lo que agregaría una opción a la que pueda pasar una función y esta función se activa si algún comando contiene un valor nulo / indefinido.
Esa función siempre obtiene el nombre del comando y los argumentos que se le pasan y el valor de retorno reemplazará los argumentos originales. De esa forma, cualquier usuario puede manejar estos valores como quiera.
Se podría aplicar la misma lógica para verdadero / falso.

@ NodeRedis / contributors @dirkbonhomme ¿qué piensas? :)

@BridgeAR No estoy de acuerdo con que null sea ​​'una señal de que algo anda mal'. Toma algo como esto:

var myIndexes = ['one','two','three'], myMulti = client.multi();

myIndexes.forEach(function(aKey) { 
  myMulti.hget(aKey,'username'); 
  myMulti.hget(aKey,'address1');  
  myMulti.hget(aKey,'address2');
});

myMulti.exec(cb);

Digamos que si 'address2' es opcional en sus datos, entonces la devolución null está bien.

Dicho esto, creo que sería un cambio importante para muchas personas, por lo que algo como lo que propones debería ser opcional, no predeterminado.

@stockholmux No estoy seguro de que hablemos de lo mismo. El valor de retorno no cambiará de ninguna manera.

Lo que quiero cambiar es que usar null dará como resultado la cadena 'null' lugar:

client.set('foo', null);
client.get('foo', function (err, res) {
    console.log(res); // 'null'
});

Tampoco romperé nada, ya que planeo desaprobar el comportamiento anterior (algunas personas pueden confiar en el comportamiento roto al desarrollar el problema) y agregar la opción para manejar esto por su cuenta ahora mismo y devolver un error de v.3.0.0 para tales valores.

¿El problema del valor 'nulo' se resuelve o no?

¿Definiría un token especial en su programa que represente el valor nulo real? Cuando el usuario establece algo en nulo, captura ese comando y reemplaza el valor nulo con su token especial. Cuando el usuario obtiene esa cosa, captura ese comando y reemplaza el token especial con un valor nulo real para el usuario.

Sólo una sugerencia. este problema es realmente molesto. Debido a que cualquier usuario en cualquier sitio podría tener un nombre llamado 'nulo', no querrá analizar el nombre de usuario con el valor nulo real;

¿Se ha realizado algún progreso o decisión en la marca "JSON. {Parse, stringify} on input"? Sería bueno que esto se hiciera automáticamente en lugar de en cualquier lógica get / set dada.

Hola @taylorzane , tengo poco tiempo en este momento, pero definitivamente está planeado implementar eso.

Eso es bueno escuchar. Si tengo algo de tiempo, puedo intentarlo, definitivamente sería bueno tenerlo, y disfruto hackear la fuente de los módulos que uso. : +1:

¿Funciona esto ahora?

Terminé usando un método diferente para serializar datos en Redis, por lo que nunca pude implementar esto.

Si no le importa compartir @taylorzane, ¿cómo está almacenando objetos JSON con campos que pueden tener valores nulos adentro usando Redis?

@slidenerd Estoy aplanando el objeto JSON y luego serializando el valor de cada nodo aplanado antes de almacenarlo en Redis. Entonces todos los valores son cadenas. Tiene un gran rendimiento incluso con miles de valores que se desserializan.

Ejemplo:

const a = {
  a: {
    b: {
      c: null,
      d: true,
      e: "hello"
    }
  }
}

const b = flatten(a)
console.log(b) /* =>
{
  '/a/b/c': null,
  '/a/b/d': true,
  '/a/b/e': 'hello'
}
*/

Object.entries(b).forEach(([key, value]) => {
  redis.set(key, JSON.stringify(value)) // or
  redis.hset('my_hash', key, JSON.stringify(value)) /*
  => "/a/b/c" -> "null"
  => "/a/b/d" -> "true"
  => "/a/b/e" -> "\"hello\""
  */
})

No dude en comunicarse conmigo en Gitter o por correo electrónico en mi perfil, si desea más orientación.

@slidenerd La otra opción es usar ReJSON para almacenar sus objetos JSON; por lo general, es una mejor opción que serializar todo manualmente y puede manejar nulos y no definidos. Es el módulo Redis, por lo que deberá tener una versión que lo admita (4.0+) e instalar el módulo en el servidor. Está más allá del alcance de este módulo Node.js (y este problema), pero resuelve el problema.

            items.push(JSON.stringify(object, (key, value) => {
                if (value === null || value === undefined) {
                    return undefined
                }
                else {
                    return isNaN(parseFloat(value)) ? value : parseFloat(value)
                }
            }))

Gracias @stockholmux, se me ocurrió una mejor solución sin usar una dependencia externa, la idea es usar la función de reemplazo en el método JSON.stringify, que resulta ser el segundo argumento

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

twappworld picture twappworld  ·  7Comentarios

gpascale picture gpascale  ·  4Comentarios

juriansluiman picture juriansluiman  ·  3Comentarios

Stono picture Stono  ·  6Comentarios

Atala picture Atala  ·  3Comentarios