Redis lebih dari sekadar penyimpanan nilai kunci.
Jadi Anda menginginkan yang berikut ini:
- pesan obrolan,
- diskusi dua orang,
- Anda tidak menyebutkan batasan waktu, jadi anggap saja Anda mengarsipkan pesan setelah beberapa saat,
- Anda juga tidak mengatakan jika Anda ingin memisahkan "utas" antara dua orang, seperti forum atau pesan berkelanjutan, seperti facebook. Saya berasumsi terus menerus.
Untuk setiap pengguna, Anda harus menyimpan pesan yang dia kirim. Misalnya APP_NAMESPACE:MESSAGES:<USER_ID>:<MESSAGE_ID>
. Kami menambahkan userId di sini sehingga kami dapat dengan mudah mengambil semua pesan yang dikirim oleh satu pengguna.
Dan, untuk setiap dua pengguna, Anda perlu melacak percakapan mereka. Sebagai kunci, Anda cukup menggunakan userid mereka APP_NAMESPACE:CONVERSATIONS:<USER1_ID>-<USER2_ID>
. Untuk memastikan Anda selalu mendapatkan percakapan bersama yang sama untuk dua pengguna, Anda dapat mengurutkan id mereka menurut abjad, sehingga pengguna 132 dan 145 akan memiliki 132:145 sebagai kunci percakapan
Jadi apa yang harus disimpan dalam "percakapan"? Mari gunakan daftar:[messageKey, messageKey, messageKey]
.
Ok, tapi apa sekarang MessageKey? Kombo userId di atas dan messageId (sehingga kita bisa mendapatkan pesan yang sebenarnya).
Jadi pada dasarnya, Anda memerlukan dua hal:
- Simpan pesan dan berikan ID
- Simpan referensi pesan ini ke percakapan yang relevan.
Dengan node dan klien redis/hiredis standar, ini akan menjadi seperti (saya akan melewatkan pemeriksaan kesalahan dll yang jelas, dan saya akan menulis ES6. Jika Anda belum dapat membaca ES6, cukup tempel ke 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);
});
});
}
Ini masih mentah dan belum teruji, tapi itulah inti dari bagaimana Anda bisa melakukannya.