Node.js хранить объекты в redis
Вот что - я хочу хранить собственные объекты JS (node.js) (ссылки сокетов флэш) в redis под определенным ключом. Когда я делаю это с простым client.set()
, он сохраняется как строка. Когда я пытаюсь получить значение, я получаю [object Object]
- просто строку.
Есть ли шанс получить эту работу? Здесь мой код:
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
});
},
Ответы
Ответ 1
Downvoters: контекст здесь - команда SET и возможность хранить произвольные объекты.
Нет, ты не можешь этого сделать. Вы должны принять тот факт, что Redis хранит все в виде строки (в конце концов, протокол основан на тексте). Redis может выполнить некоторую оптимизацию и преобразовать некоторые значения в целые числа, но это ваше дело, а не ваше.
Если вы хотите хранить произвольные объекты в Redis, убедитесь, что вы их сериализовали перед сохранением и десериализацией после получения.
Я не уверен, если вы можете сделать это с объектами сокета, хотя. Они просто описывают системный ресурс (открытое соединение), в конце концов (например, сокеты TCP). Если вам удастся сериализовать описание и десериализовать его на другой машине, эта другая машина не будет подключена.
Ответ 2
Поскольку сокет имеет тип Object
, вам необходимо преобразовать объект в строку перед сохранением, а при извлечении сокета необходимо преобразовать его обратно в объект.
Ты можешь использовать
JSON.stringify(socket)
преобразовать в строку и
JSON.parse(socketstr)
преобразовать обратно в объект.
Редактировать:
С момента выпуска версии 2.0.0
мы можем хранить объекты в виде хэшей в Redis.
client.hmset("hosts", "mjr", "1", "another", "23", "home", "1234");
client.hgetall("hosts", function (err, obj) {
console.dir(obj);
});
https://redis.io/commands/hset
https://github.com/NodeRedis/node_redis
Ответ 3
В приведенном ниже решении не решается весь смысл использования redis - обмениваться данными между экземплярами кластера. Хранение идентификатора конкретного экземпляра в redis будет бессмысленным для другого экземпляра, который пытается использовать этот идентификатор.
Однако существует "hmset", который может быть вызван с объектом, и он будет устанавливать каждое поле объекта как отдельное поле redis в том же ключе. И он будет преобразован обратно в объект при вызове hgetall. К сожалению, я не думаю, что он обрабатывает вложенные объекты или массивы внутри объекта, а только простые свойства, значения которых могут быть сохранены "toString()".
Итак, такой объект, как
client.hmset("myhashkey",{a:1, b:2, c:'xxx'})
отлично работает и может быть найден с помощью
client.hmget("myhashkey", function(obj) {
console.log(obj);
});
Не так много:
client.hmset("myhashkeynested",{a:1, b:2, c:'xxx', d: { d1: 'x', d2: 'y'}});
Ответ 4
Я также нашел, что это невероятно полезный инструмент, особенно если вы направляете JSON из API в свой интерфейс:
node-redis-jsonify
Если вы получаете огромный блок JSON и не можете хранить его как определенный хэш, его строгая при сохранении позволит вам извлечь весь json вместо "[object Object]".
Ответ 5
Я верю, что когда вы храните объект, внутренне, перед тем, как вызывается память object.toString()
, и это значение, которое сохраняется.
({a: 1}).toString() # "[object Object]"
Что вам нужно сделать, это использовать JSON.encode и JSON.parse.
Вы не можете хранить (скрытые, двоичные) ссылки.
В противном случае вы можете сделать переписку между целыми числами и сокетами и хранить целые числа.
Ответ 6
Вы можете сохранить ссылку на объект JavaScript, используя такую технику. В основном, он расширяет Object.prototype(не обязательно), и вы можете вызвать radd(), чтобы добавить произвольную ссылку на rhash {}, а затем вернуть объект с помощью rget(). "Ссылка" - это строка, поэтому она будет вписываться в Redis. Это означает, что вам не нужно будет .stringify() и .parse() помещать/получать копию в базе данных. Однако данные объекта будут уничтожены, если Node выключится, если его сериализован.
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
Хорошо, если вы думаете об этом, объекты javascript - это ключи, значения которых могут ссылаться на другие объекты, а в случае сокетов возможно нативные объекты. Итак, если redis является внешним для исполняемого javascript, как он сможет хранить ссылку на этот объект?
// 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