Подтвердить что ты не робот

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
    });
  },
4b9b3361

Ответ 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