2012-01-01 6 views
35

Вот что - я хочу хранить собственные объекты JS (node.js) (ссылки сокетов флэш) в redis под определенным ключом. Когда я делаю это с простым client.set(), он хранится в виде строки. Когда я пытаюсь получить значение, я получаю [object Object] - просто строку.node.js хранить объекты в redis

Есть ли шанс получить эту работу? Вот мой код:

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

Что в этой строке? – clyfe

+0

Вы не можете хранить ссылки на javascript в некоторой форме базы данных, потому что объекты исчезают, когда сервер идет вниз – Raynos

+0

@clyfe: [object Object] – Pono

ответ

19

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

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

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

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

+3

Не уверен, как это было в 2012 году, но по крайней мере сейчас в 2016 году Redis ** делает * * хранить произвольные объекты, а не ** хранить все как строку. Вам просто нужно использовать разные команды/методы для использования этой функции. См. Ответ Джейсона Ловемана для лучшего решения: http://stackoverflow.com/a/21490063/130691 – JMTyler

+2

@JMTyler: ссылки на документы? Redis не сохраняет объекты __arbitrary__. Всего несколько предварительно определенных типов (строка, хеш, список и т. Д.). И если вы сохраните что-то с помощью команды 'SET', она будет сохранена в виде строки. Ни в коем случае. –

+0

Да, SET хранится как строка, но это, очевидно, не единственная команда Redis. Вы не можете утверждать, что как работает SET, так это то, как работает Redis. 'hash' ** ** другое слово для объекта в зависимости от того, какой язык/платформа вы используете, поэтому я не вижу, что такое ваш аргумент. Тот факт, что вы упоминаете хэши, означает, что вы, очевидно, знаете, что вы можете хранить более сложные данные, чем просто строки. – JMTyler

87

Поскольку сокет имеет тип «Объект», вам необходимо преобразовать объект в строку перед сохранением и при извлечении сокета необходимо преобразовать его обратно в объект. Вы можете использовать

JSON.stringify(socket) 

преобразовать в строку и

JSON.parse(socketstr) 

преобразовать обратно в объект.

+8

Теперь это ответ! Вы ничего не можете сделать, это никогда не ответит. tnx Шон. – Maziyar

+1

Это должен быть принятый ответ. – moeiscool

+0

Почему это не принято? Возьмите верх. –

3

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

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

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

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

-1

Вы можете сохранить ссылку на объект 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

Не изменяйте 'Object.prototype'! – Eric

+0

Почему вам нужно связать это с Object.prototype и сделать эти методы get/set вместо того, чтобы просто делать hash = {}, hash [key] = object? –

24

Решение ниже не решает проблему использования 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

Retrieve by: 'client.hgetall (" the-key-name ", function (err, obj) {// ...})', для 'hmget' нужны' имена полей'. –

+0

Этот ответ требует большего количества оборотов! Принятый ответ неверен. – JMTyler

+2

@JMTyler: это не поможет хранить произвольные объекты js (в этом случае сокеты). –

-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 
+1

Использование eval - это всегда плохая идея – Mauro

6

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

node-redis-jsonify

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

Смежные вопросы