Redis là nơi lưu trữ khóa-giá trị nhiều hơn.
Vì vậy, bạn muốn những thứ sau:
- tin nhắn trò chuyện,
- cuộc thảo luận của hai người,
- bạn đã không đề cập đến giới hạn thời gian, vì vậy hãy giả sử rằng bạn lưu trữ thư sau một thời gian,
- bạn cũng không cho biết bạn có muốn các "chuỗi" riêng biệt giữa hai người, như diễn đàn hoặc tin nhắn liên tục, như facebook hay không. Tôi giả định là liên tục.
Đối với mỗi người dùng, bạn phải lưu trữ tin nhắn mà họ gửi. Giả sử APP_NAMESPACE:MESSAGES:<USER_ID>:<MESSAGE_ID>
. Chúng tôi thêm userId tại đây để chúng tôi có thể dễ dàng truy xuất tất cả các tin nhắn do một người dùng gửi.
Và, đối với mỗi hai người dùng, bạn cần theo dõi các cuộc trò chuyện của họ. Là một khóa, bạn có thể chỉ cần sử dụng mã sử dụng của chúng APP_NAMESPACE:CONVERSATIONS:<USER1_ID>-<USER2_ID>
. Để đảm bảo bạn luôn nhận được cùng một cuộc trò chuyện được chia sẻ cho hai người dùng, bạn có thể sắp xếp id của họ một cách linh hoạt, để người dùng 132 và 145 đều có 132:145 làm khóa hội thoại
Vậy những gì cần lưu trữ trong các cuộc “trò chuyện”? Hãy sử dụng danh sách:[messageKey, messageKey, messageKey]
.
Ok, nhưng tin nhắn bây giờ là gì? Kết hợp userId ở trên và một messageId (để chúng ta có thể nhận được thông báo thực tế).
Vì vậy, về cơ bản, bạn cần hai thứ:
- Lưu trữ tin nhắn và cung cấp cho nó một ID
- Lưu trữ tham chiếu đến tin nhắn này cho cuộc trò chuyện có liên quan.
Với nút và ứng dụng redis / Rentis tiêu chuẩn, điều này sẽ giống như (Tôi sẽ bỏ qua các kiểm tra lỗi, v.v. rõ ràng, và tôi sẽ viết ES6. Nếu bạn chưa thể đọc ES6, chỉ cần dán nó vào babel):
// assuming the init connects to redis and exports a redisClient
import redisClient from './redis-init';
import uuid from `node-uuid`;
export function storeMessage(userId, toUserId, message) {
return new Promise(function(resolve, reject) {
// give it an id.
let messageId = uuid.v4(); // gets us a random uid.
let messageKey = `${userId}:${messageId}`;
let key = `MY_APP:MESSAGES:${messageKey}`;
client.hmset(key, [
"message", message,
"timestamp", new Date(),
"toUserId", toUserId
], function(err) {
if (err) { return reject(err); }
// Now we stored the message. But we also want to store a reference to the messageKey
let convoKey = `MY_APP:CONVERSATIONS:${userId}-${toUserId}`;
client.lpush(convoKey, messageKey, function(err) {
if (err) { return reject(err); }
return resolve();
});
});
});
}
// We also need to retreive the messages for the users.
export function getConversation(userId, otherUserId, page = 1, limit = 10) {
return new Promise(function(resolve, reject) {
let [userId1, userId2] = [userId, otherUserId].sort();
let convoKey = `MY_APP:CONVERSATIONS:${userId1}-${userId2}`;
// lets sort out paging stuff.
let start = (page - 1) * limit; // we're zero-based here.
let stop = page * limit - 1;
client.lrange(convoKey, start, stop, function(err, messageKeys) {
if (err) { return reject(err); }
// we have message keys, now get all messages.
let keys = messageKeys.map(key => `MY_APP:MESSAGES:${key}`);
let promises = keys.map(key => getMessage(key));
Promise.all(promises)
.then(function(messages) {
// now we have them. We can sort them too
return resolve(messages.sort((m1, m2) => m1.timestamp - m2.timestamp));
})
.catch(reject);
});
});
}
// we also need the getMessage here as a promise. We could also have used some Promisify implementation but hey.
export function getMessage(key) {
return new Promise(function(resolve, reject) {
client.hgetall(key, function(err, message) {
if (err) { return reject(err); }
resolve(message);
});
});
}
Bây giờ điều đó còn thô sơ và chưa được kiểm tra, nhưng đó là ý chính của cách bạn có thể làm điều này.