node.js以redis格式存储对象

时间:2012-01-01 19:05:50

标签: object node.js redis

这是事情 - 我希望在某个密钥下的redis中存储本机JS(node.js)对象(闪存套接字引用)。当我使用简单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 个答案:

答案 0 :(得分:112)

由于套接字的类型为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

答案 1 :(得分:30)

Downvoters:这里的上下文是SET命令和存储任意对象的能力。

不,你不能这样做。您应该接受Redis将所有内容存储为字符串的事实(该协议毕竟是基于文本的)。 Redis可以执行一些优化并将一些值转换为整数,但这是它的业务,而不是你的业务。

如果要在Redis中存储任意对象,请确保在检索之后对其进行序列化,然后再进行保存和反序列化。

但是,我不确定你是否可以使用套接字对象。毕竟它们只是描述了一个系统资源(一个开放的连接)(例如TCP套接字)。如果您设法序列化描述并在另一台机器上反序列化,则该另一台机器将没有连接。

答案 2 :(得分:30)

以下解决方案无法解决使用redis的全部问题 - 跨群集实例共享数据。在redis中存储特定于实例的id对于尝试使用该id的另一个实例将毫无意义。

但是,可以使用对象调用“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'}});

答案 3 :(得分:6)

我还发现这是一个非常有用的工具,特别是如果你将JSON从API引导到你的前端:

node-redis-jsonify

如果您正在接收大量JSON并且无法存储为特定哈希,则在存储时对其进行字符串化将允许您检索整个json而不仅仅是" [object Object] "

答案 4 :(得分:3)

我相信当你在调用存储object.toString()之前在内部存储对象时,这就是存储的值。

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

您需要做的是使用JSON.encode和JSON.parse。

您无法存储(隐藏的,二进制)参考文献 否则,您可能能够在整数和套接字之间建立对应关系,并存储整数。

答案 5 :(得分:-2)

您可以使用这样的技术保存对JavaScript对象的引用。基本上,它扩展了Object.prototype(不必),你可以调用radd()来为rhash {}添加自定义引用,然后用rget()检索对象。 “引用”是一个字符串,因此它适合Redis。这意味着您不必使用.stringify()和.parse()来在数据库中放置/获取副本。但是,当节点关闭时,对象的数据将被销毁,除非它被序列化。

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();

答案 6 :(得分:-2)

好吧,如果你考虑一下,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