2012-01-01 2 views
35

Đây là điều - Tôi muốn lưu trữ các đối tượng JS (node.js) nguyên gốc (tham chiếu socket flash) trong redis theo một khóa nhất định. Khi tôi làm điều đó với đơn giản client.set() nó được lưu trữ như một chuỗi. Khi tôi cố gắng để có được giá trị tôi nhận được [object Object] - chỉ là một chuỗi.đối tượng lưu trữ node.js trong redis

Bất kỳ cơ hội nào để làm việc này? Dưới đây là mã của tôi:

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

Chuỗi đó có gì? – clyfe

+0

bạn không thể lưu trữ tham chiếu đến javascript ở một số dạng cơ sở dữ liệu vì các đối tượng biến mất khi máy chủ rơi xuống – Raynos

+0

@clyfe: [object Object] – Pono

Trả lời

19

Downvoters: bối cảnh ở đây được đặt lệnh và khả năng lưu trữ đối tượng tùy ý.

Không, bạn không thể làm điều đó. Bạn nên chấp nhận thực tế là Redis lưu trữ tất cả mọi thứ dưới dạng một chuỗi (giao thức dựa trên văn bản, sau khi tất cả). Redis có thể thực hiện một số tối ưu hóa và chuyển đổi một số giá trị thành số nguyên, nhưng đó là doanh nghiệp chứ không phải của bạn.

Nếu bạn muốn lưu trữ tùy ý đối tượng trong Redis, hãy đảm bảo rằng bạn tuần tự hóa chúng trước khi lưu và hủy tuần tự sau khi truy xuất.

Tôi không chắc chắn nếu bạn có thể làm điều đó với các đối tượng ổ cắm, mặc dù. Họ chỉ đơn giản là mô tả một tài nguyên hệ thống (một kết nối mở), sau khi tất cả (ổ cắm TCP, ví dụ). Nếu bạn quản lý để tuần tự hóa mô tả và deserialize nó trên một máy khác, rằng máy khác sẽ không có kết nối.

+3

Không chắc chắn nó đã trở lại vào năm 2012 như thế nào, nhưng ít nhất là vào năm 2016 Redis ** * lưu trữ các đối tượng tùy ý, nó không ** lưu trữ mọi thứ dưới dạng chuỗi. Bạn chỉ cần sử dụng các lệnh/phương thức khác nhau để sử dụng chức năng đó. Xem câu trả lời của Jason Loveman để có giải pháp tốt hơn: http://stackoverflow.com/a/21490063/130691 – JMTyler

+2

@JMTyler: liên kết đến tài liệu? Redis không lưu trữ các đối tượng __arbitrary__. Chỉ một vài loại được xác định trước (chuỗi, băm, danh sách, v.v.). Và nếu bạn lưu trữ một cái gì đó thông qua lệnh 'SET', nó sẽ được lưu trữ như một chuỗi. Không còn cách nào khác. –

+0

Có, SET lưu trữ dưới dạng chuỗi, nhưng rõ ràng đó không phải là lệnh duy nhất mà Redis có. Bạn không thể tuyên bố rằng cách hoạt động của SET là cách tất cả Redis hoạt động. 'hash' ** là ** một từ khác cho đối tượng tùy thuộc vào ngôn ngữ/nền tảng bạn đang sử dụng, vì vậy tôi không thấy đối số của bạn là gì. Thực tế là bạn đề cập đến băm có nghĩa là bạn rõ ràng biết rằng bạn có thể lưu trữ dữ liệu phức tạp hơn chỉ là chuỗi. – JMTyler

87

Vì ổ cắm thuộc loại 'Đối tượng', bạn cần chuyển đổi đối tượng thành chuỗi trước khi lưu trữ và khi truy xuất ổ cắm, cần phải chuyển đổi nó trở lại đối tượng. Bạn có thể sử dụng

JSON.stringify(socket) 

để chuyển đổi thành một chuỗi và

JSON.parse(socketstr) 

để chuyển đổi trở lại một đối tượng.

+8

Bây giờ đó là câu trả lời! Bạn không thể làm điều gì đó không bao giờ là câu trả lời. tnx Shawn. – Maziyar

+1

đây phải là câu trả lời được chấp nhận. – moeiscool

+0

Tại sao đây không phải là câu trả lời được chấp nhận? Có một upvote. –

3

Tôi tin rằng khi bạn lưu trữ đối tượng, trong nội bộ, trước khi lưu trữ object.toString() được gọi và đó là giá trị được lưu trữ.

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

Điều bạn cần làm là sử dụng JSON.encode và JSON.parse.

Bạn không thể lưu trữ các tham chiếu (ẩn, nhị phân).
Nếu không, bạn có thể thực hiện tương ứng giữa số nguyên và ổ cắm và lưu số nguyên.

-1

Bạn có thể lưu tham chiếu đến đối tượng JavaScript, sử dụng kỹ thuật như thế này. Về cơ bản, nó mở rộng Object.prototype (không cần phải) và bạn có thể gọi radd() để thêm một tham chiếu tùy chỉnh vào rhash {}, sau đó lấy đối tượng bằng rget(). "Tham chiếu" là một chuỗi sao cho nó sẽ vừa với Redis. Điều này có nghĩa là bạn sẽ không phải. Stringify() và .parse() để đặt/nhận một bản sao trong cơ sở dữ liệu. Tuy nhiên, dữ liệu của đối tượng sẽ bị hủy khi Node tắt trừ khi được tuần tự hóa.

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

Không sửa đổi 'Object.prototype'! – Eric

+0

tại sao bạn cần phải ràng buộc điều này với Object.prototype và làm cho các phương thức get/set này thay vì chỉ làm hash = {}, hash [key] = object? –

24

Giải pháp dưới đây không giải quyết toàn bộ điểm sử dụng redis - để chia sẻ dữ liệu trên các trường hợp cụm. Việc lưu trữ một id cụ thể của cá thể bằng redis sẽ vô nghĩa đối với một cá thể khác cố sử dụng id đó.

Tuy nhiên, có "hmset" có thể được gọi với một đối tượng và nó sẽ đặt từng trường đối tượng dưới dạng trường redis riêng biệt trong cùng một khóa.Và nó sẽ được chuyển đổi trở lại một đối tượng khi bạn gọi hgetall. Thật không may, tôi không nghĩ rằng nó xử lý các đối tượng lồng nhau hoặc mảng trong một đối tượng, chỉ các thuộc tính đơn giản có giá trị có thể được lưu trữ bởi "toString()".

Vì vậy, một đối tượng như

client.hmset("myhashkey",{a:1, b:2, c:'xxx'}) 

hoạt động tuyệt vời và có thể được lấy ra với

client.hmget("myhashkey", function(obj) { 
    console.log(obj); 
}); 

Không quá nhiều cho:

client.hmset("myhashkeynested",{a:1, b:2, c:'xxx', d: { d1: 'x', d2: 'y'}}); 
+4

Lấy bởi: 'client.hgetall (" tên-chìa khóa ", hàm (err, obj) {// ...})', cho 'hmget' cần' tên trường'. –

+0

Câu trả lời này cần nhiều ưu điểm hơn! Câu trả lời được chấp nhận là sai. – JMTyler

+2

@JMTyler: điều này sẽ không giúp đỡ trong việc lưu trữ các đối tượng js tùy ý (ổ cắm, trong trường hợp này). –

-2

tốt nếu bạn nghĩ về nó các đối tượng javascript là các khóa của những giá trị có thể tham chiếu đến các đối tượng khác và trong trường hợp ổ cắm có thể là các đối tượng gốc. Vì vậy, nếu redis là bên ngoài để thực hiện javascript như thế nào nó sẽ có thể lưu trữ một tham chiếu đến đối tượng đó?

// 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

sử dụng eval luôn luôn là một ý tưởng tồi – Mauro

6

Tôi cũng thấy điều này như là một công cụ vô cùng hữu ích, đặc biệt là nếu bạn đang channeling JSON từ một API để front-end của bạn:

node-redis-jsonify

Nếu bạn nhận được một khối khổng lồ của JSON và không thể lưu trữ dưới dạng băm cụ thể, xâu chuỗi nó trong khi lưu trữ sẽ cho phép bạn truy xuất toàn bộ json thay vì chỉ "[object Object]".