2012-01-01 46 views
35

Aquí está la cosa: quiero almacenar objetos JS (node.js) nativos (referencias de sockets flash) en redis bajo una cierta clave. Cuando hago eso con simple client.set(), se almacena como una cadena. Cuando trato de obtener valor, obtengo [object Object], solo una cadena.node.js almacenar objetos en redis

¿Alguna posibilidad de que funcione? Aquí está mi código:

addSocket : function(sid, socket) { 
    client.set(sid, socket); 
    }, 

    getSocket : function(sid) { 
    client.get(sid, function(err, reply) { 
     // cant't get an object here. All I get is useless string 
    }); 
    }, 
+0

¿Qué hay en esa cadena? – clyfe

+0

no puede almacenar referencias a javascript en alguna forma de base de datos porque los objetos desaparecen cuando el servidor deja de funcionar – Raynos

+0

@clyfe: [object Object] – Pono

Respuesta

19

Downvoters: el contexto aquí es el mando y capacidad de almacenar objetos arbitrarios SET.

No, no puedes hacer eso. Debe aceptar el hecho de que Redis almacena todo como una cadena (el protocolo está basado en texto, después de todo). Redis puede realizar algunas optimizaciones y convertir algunos valores en enteros, pero ese es su negocio, no el suyo.

Si desea almacenar objetos arbitrarios en Redis, asegúrese de serializarlos antes de guardarlos y deserializarlos después de recuperarlos.

No estoy seguro de si puede hacer eso con objetos de socket. Simplemente describen un recurso del sistema (una conexión abierta), después de todo (sockets TCP, por ejemplo). Si logra serializar la descripción y deserializarla en otra máquina, esa otra máquina no tendrá la conexión.

+3

No estoy seguro de cómo fue en 2012, pero al menos ahora en 2016 Redis ** does * * almacena objetos arbitrarios, ** no ** almacena todo como una cadena. Solo necesita usar diferentes comandos/métodos para usar esa funcionalidad. Vea la respuesta de Jason Loveman para una mejor solución: http://stackoverflow.com/a/21490063/130691 – JMTyler

+2

@JMTyler: ¿enlaces a los documentos? Redis no almacena objetos __arbitrary__. Solo unos pocos tipos predeterminados (cadena, hash, lista, etc.). Y si almacena algo mediante el comando 'SET', se almacenará como una cadena. No hay forma de evitar esto. –

+0

Sí, SET almacena como una cadena, pero obviamente este no es el único comando que tiene Redis. No se puede afirmar que el funcionamiento de SET es la forma en que funciona Redis. 'hash' ** es ** otra palabra para objeto dependiendo de qué idioma/plataforma está usando, así que no veo cuál es su argumento. El hecho de que menciones hashes significa que obviamente sabes que puedes almacenar datos más complejos que solo cadenas. – JMTyler

87

Dado que el zócalo es del tipo 'Objeto', debe convertir el objeto en una cadena antes de almacenarlo y, al recuperar el zócalo, debe volver a convertirlo en un objeto. Puede utilizar

JSON.stringify(socket) 

a convertir en una cadena y

JSON.parse(socketstr) 

convertir de nuevo a un objeto.

+8

¡Esa es una respuesta! No puedes hacer algo nunca es una respuesta. tnx Shawn. – Maziyar

+1

esta debería ser la respuesta aceptada. – moeiscool

+0

¿Por qué no es esta la respuesta aceptada? Toma un voto positivo. –

3

Creo que cuando se almacena el objeto, internamente, se llama al almacenamiento object.toString() y ese es el valor que se almacena.

({a: 1}).toString() # "[object Object]" 

Lo que debes hacer es usar JSON.encode y JSON.parse.

No se pueden almacenar referencias (ocultas, binarias).
De lo contrario, es posible que pueda hacer una correspondencia entre enteros y sockets, y almacenar enteros.

-1

Puede guardar una referencia al objeto JavaScript, usando una técnica como esta. Básicamente, amplía Object.prototype (no tiene que) y puede llamar a radd() para agregar una referencia personalizada a rhash {}, luego recuperar el objeto con rget(). La "referencia" es una cadena por lo que cabe directamente en Redis. Esto significa que no tendrá que .stringify() y .parse() para poner/obtener una copia en la base de datos. Sin embargo, los datos del objeto se destruirán cuando el Nodo se apague, a menos que esté serializado.

var OBJECT = Object.prototype; 
OBJECT.rhash = {}; 
OBJECT.rset = function(id, object) { 
    OBJECT.rhash[id] = object; 
    return id; 
}; 
OBJECT.rget = function(id) { 
    return OBJECT.rhash[id]; 
}; 

var dog = { 
    name: "Skippy", 
    food: "Bacon", 
    bark: function() { 
    alert(this.name + "!"); 
    } 
}; 

var id = OBJECT.rset("a123", dog); 
var ref = OBJECT.rget("a123"); 
ref.bark(); 
+7

¡No modifique 'Object.prototype'! – Eric

+0

¿Por qué necesita vincular esto al Object.prototype y hacer estos métodos get/set en lugar de simplemente hacer hash = {}, hash [key] = object? –

24

La siguiente solución no resuelve el problema de utilizar redis: para compartir datos entre instancias de clúster. Almacenar un ID específico de instancia en redis no tendrá sentido para otra instancia que intente usar ese ID.

Sin embargo, hay "hmset" que se puede llamar con un objeto y establecerá cada campo de objeto como un campo redis separado en la misma clave.Y se convertirá nuevamente en un objeto cuando llame a hgetall. Desafortunadamente, no creo que maneje objetos anidados o matrices dentro de un objeto, solo propiedades simples cuyos valores pueden ser almacenados por "toString()".

lo tanto un objeto como

client.hmset("myhashkey",{a:1, b:2, c:'xxx'}) 

funciona muy bien y se pueden recuperar con

client.hmget("myhashkey", function(obj) { 
    console.log(obj); 
}); 

No tanto por:

client.hmset("myhashkeynested",{a:1, b:2, c:'xxx', d: { d1: 'x', d2: 'y'}}); 
+4

Recuperar por: 'client.hgetall (" the-key-name ", function (err, obj) {// ...})', para 'hmget' need' field names'. –

+0

¡Esta respuesta necesita más votos ascendentes! La respuesta aceptada es falsa. – JMTyler

+2

@JMTyler: esto no ayudará a almacenar objetos arbitrarios js (sockets, en este caso). –

-2

bien si se piensa en ello Javascript objetos son Las claves cuyos valores pueden hacer referencia a otros objetos, y en el caso de los sockets, pueden ser objetos nativos. Entonces, si redis es externo al javascript de ejecución, ¿cómo podrá almacenar una referencia a ese objeto?

// a and b exist inside the executing javascript, not in the external O/S 
a = {} 
b = {} 

var obj = { 
    'one': a, 
    'two': b 
} 

// how can redis possibly store references to obj, a or b when this application exits? 
redis.set('obj', obj) 

// same as.. 
redis.set('obj', obj.toString()) /*or*/ redis.set('obj', "" + obj) 

// same as.. 
redis.set('obj', "[object Object]") 


// the trick is to stringify the object 
redis.set('obj', JSON.stringify(obj)) 

// same as.. 
redis.set('obj', "{'one':{},'two':{}}") 

// here redis does not have to store the actual object references but rather a json string representing the object 

// this could also work 
redis.set('obj', "{'one':a,'two':b}") 

// where you would then do: 
obj = eval(redis.get('obj')) 
// provided that a and b have already been initialized 
+1

uso eval es siempre una mala idea – Mauro

6

También he encontrado que se trata de una herramienta muy útil, especialmente si usted está canalizando JSON de una API para el front-end:

node-redis-jsonify

Si se está recibiendo un enorme bloque de JSON y no puede almacenar como un hash específico, al codificarlo mientras se almacena, le permitirá recuperar el json completo en lugar de simplemente "[object object]".

Cuestiones relacionadas