node.js хранит объекты в Redis - PullRequest
       19

node.js хранит объекты в Redis

44 голосов
/ 01 января 2012

Вот в чем дело - я хочу хранить собственные объекты JS (node.js) (ссылки на flash-сокеты) в 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
    });
  },

Ответы [ 7 ]

115 голосов
/ 01 января 2012

Поскольку сокет имеет тип Object, необходимо преобразовать объект в строку перед сохранением, а при извлечении сокета необходимо преобразовать его обратно в объект.

Вы можете использовать

JSON.stringify(socket) 

для преобразования в строку и

JSON.parse(socketstr) 

для преобразования обратно в объект.

Edit:

С момента выпуска версии 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

32 голосов
/ 01 февраля 2014

Приведенное ниже решение не решает весь смысл использования 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'}});
32 голосов
/ 01 января 2012

Downvoters: контекст здесь - команда SET и возможность хранить произвольные объекты.

Нет, вы не можете этого сделать.Вы должны принять тот факт, что Redis хранит все в виде строки (в конце концов, протокол основан на тексте).Redis может выполнить некоторую оптимизацию и преобразовать некоторые значения в целые числа, но это ваше дело, а не ваше.

Если вы хотите хранить произвольные объекты в Redis, убедитесь, что вы сериализовали их перед сохранениеми десериализовать после извлечения.

Я не уверен, что вы можете сделать это с объектами сокетов.Они просто описывают системный ресурс (открытое соединение), в конце концов (например, сокеты TCP).Если вам удастся сериализовать описание и десериализовать его на другой машине, эта другая машина не будет подключена.

6 голосов
/ 10 апреля 2015

Я также обнаружил, что это невероятно полезный инструмент, особенно если вы направляете JSON из API на ваш интерфейс:

node-redis-jsonify

Если вы получаете огромный блок JSON и не можете сохранить его в качестве определенного хеша, его строковое преобразование во время сохранения позволит вам получить весь JSON вместо просто «[объект объекта]».

3 голосов
/ 01 января 2012

Я верю, что когда вы сохраняете объект внутри, перед хранением вызывается object.toString(), и это значение сохраняется.

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

Что вам нужно сделать, это использовать JSON.encode и JSON.parse.

Нельзя хранить (скрытые, двоичные) ссылки.
В противном случае вы могли бы сделать соответствие между целыми числами и сокетами и хранить целые числа.

0 голосов
/ 27 апреля 2014

хорошо, если вы об этом думаете, объекты 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
0 голосов
/ 01 января 2012

Вы можете сохранить ссылку на объект 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();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...