微信开发系列之七 - 使用Redis存储微信聊天记录

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,经济版 1GB 1个月
简介: 微信开发系列之七 - 使用Redis存储微信聊天记录

In the second blog Wechat development series 2 – development Q&A service using nodejs of this series, we have developed a kind of Q&A service in Wechat which leverages a free Tuning Restful service so that you could chat with this service:

image.pngIn this blog, I will show the steps how to store all of those conversation logs via Redis, so that you can review the conversations within Wechat app or delete them if necessary.


Implemented feature

Two new sub menus “Review” and “Delete” are developed under menu “Conversation”

image.pngOnce Review menu is pressed, the conversation log will be read out from Redis and displayed in Wechat app:

image.pngDelete menu will trigger the deletion of the conversation log belonging to current user who has pressed it. Once conversation is deleted, corresponding notification will be sent out if user has pressed the Review menu again.

image.pngImplementation detail

(1) Since as before my WeChat server runs on Heroku, which supports Redis as well.

Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache and message broker. It supports data structures such as strings, hashes, lists, sets, sorted sets with range queries, bitmaps, hyperloglogs and geospatial indexes with radius queries.

In this blog I will use Redis to store conversation logs.


It is very easy in Heroku to enable an application with Redis support, just select your application from drop down list and press Continue:

image.pngOnce done, in you application dashboard you can see the Redis as addon:

image.pngYou don’t need any additional configuration on Redis, which is now ready for development.

(2) follow the steps in blog Wechat development series 5 – embedded your UI5 application to Wechat app to create menu and two submenu.


It is enough to create menu via postman. You’d better first remove the old menu done in previous blog and recreate a new menu from scratch:

image.pngthe source code of HTTP post payload for the new menu creation:

image.png(3) Now every time when Tuning service receives a query from end user and is ready to send the answer of this query, add logic to record this conversation detail.

Just add one line for logging in tuning.js:

image.png

Date.prototype.today = function () { 
    return ((this.getDate() < 10)?"0":"") + this.getDate() +"/"+(((this.getMonth()+1) < 10)?"0":"") + (this.getMonth()+1) +"/"+ this.getFullYear();
}
Date.prototype.timeNow = function () {
     return ((this.getHours() < 10)?"0":"") + this.getHours() +":"+ ((this.getMinutes() < 10)?"0":"") + this.getMinutes() +":"+ ((this.getSeconds() < 10)?"0":"") + this.getSeconds();
}
function logConversation(wholeContent, question, answer){
  var fromUserId = formattedValue(getXMLNodeValue('FromUserName', wholeContent));
  var toUserId = formattedValue(getXMLNodeValue('ToUserName', wholeContent));
  var fromUserName = config.userMap[fromUserId] || fromUserId;
  var toUserName = config.userMap[toUserId] || toUserId;
  var datetime = "Send Time: " + new Date().today() + "  " + new Date().timeNow();
  redisClient.insert(toUserId, objectToString(fromUserName, toUserName, datetime, question, answer));
};
function objectToString(fromUserName, toUserName, datetime, question, answer){
  var record = {
    "from": fromUserName,
    "to": toUserName,
    "sendTime": datetime,
    "question": question,
    "answer": answer
  };
  return JSON.stringify(record); 
}
function getList(sToUserOpenId){
  return redisClient.getList(sToUserOpenId);
}
function deleteLog(sToUserOpenId){
  return redisClient.clearList(sToUserOpenId);
}
var oService = {
  log: logConversation,
  getLog: getList,
  deleteLog: deleteLog
}
module.exports = oService;

Redis service wrapper module is implemented in file redisClient.js.


This wrapper module is built on top of open source Redis module for nodejs, whose source code could be found from github: https://github.com/NodeRedis/node_redis

var redis = require("redis"),
  client = redis.createClient(process.env.REDIS_URL || "redis://h:p99a8dd0d92871b9ffe7a026e6d70beecd7f2a0e743fa1e2840a58ce048f41c4a@ec2-34-237-158-248.compute-1.amazonaws.com:9479"); // by default localhost will be used!!
client.on("error", function (err) {
    console.log("Trouble......... Redis startup failed: " + err);
});
function insertIntoList(sOpenId, oElement){
  client.lpush(sOpenId, oElement);
}
function clearList(sOpenId){
  return new Promise(function(resolve,reject){
    client.del(sOpenId, function(error, count){
        if(error){
            console.log("error when clear list:" + error);
            reject(error);
        }
        var reply = "list clear successfully";
        console.log(reply);
        resolve(reply); 
    });
  });
}
function getListContent(sOpenId){
  return new Promise(function(resolve,reject){
    client.lrange(sOpenId, 0, -1, function(err, reply) {
        console.log("content for list: " + sOpenId + " **********: " + reply + "***");
        var content = reply;
        if( content == ""){
          content = "no conversation log found.";
                console.log("reject content: " + content);
                reject(content);
        }
            else {
          resolve(formatToWechat(content));
            }
    });
     });
}
function formatToWechat(raw){
    var formatted = "[" + raw + "]";
    var result = "";
    var logs = JSON.parse(formatted);
    for( var i = 0; i < logs.length; i++){
        var record = "record[" + i + "]:" + " [[from]] " + logs[i].from
         + " [[to]] " + logs[i].to + " [[sendTime]] " + logs[i].sendTime + " [[question]] " + logs[i].question
        + " [[answer]] " + logs[i].answer;
        if( i === 0){
            result = record;
        }
        else{
            result = result + "\n" + "\n" + record;
        }
    }
    return result;
}
var oRedisClient = {
  insert: insertIntoList,
  clearList: clearList,
  getList: getListContent
};
module.exports = oRedisClient;

(4) implement event handling logic when menu “review” and “delete” are pressed.


Corresponding API provided by Redis are called to read log records from Redis or just clear the list where the log records are stored.

image.png

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
相关文章
|
3天前
|
存储 消息中间件 NoSQL
中间件键值存储模型Redis
【7月更文挑战第11天】
12 3
|
10天前
|
存储 NoSQL Java
Redis10------Set类型,存在着无序的特征存储的顺序和插入的顺序是无关的,set集合的一大特点是不可重复,在redis中支持交集插集等特殊功能,好友列表,共同关注等等
Redis10------Set类型,存在着无序的特征存储的顺序和插入的顺序是无关的,set集合的一大特点是不可重复,在redis中支持交集插集等特殊功能,好友列表,共同关注等等
|
11天前
|
存储 Java
Redis08命令-Hash类型,也叫散列,其中value是一个无序字典,类似于java的HashMap结构,Hash结构可以将对象中的每个字段独立存储,可以针对每字段做CRUD
Redis08命令-Hash类型,也叫散列,其中value是一个无序字典,类似于java的HashMap结构,Hash结构可以将对象中的每个字段独立存储,可以针对每字段做CRUD
|
11天前
|
存储 NoSQL Redis
Redis07命令-String类型字符串,不管是哪种格式,底层都是字节数组形式存储的,最大空间不超过512m,SET添加,MSET批量添加,INCRBY age 2可以,MSET,INCRSETEX
Redis07命令-String类型字符串,不管是哪种格式,底层都是字节数组形式存储的,最大空间不超过512m,SET添加,MSET批量添加,INCRBY age 2可以,MSET,INCRSETEX
|
12天前
|
存储 缓存 NoSQL
网页设计,若依项目修改(It must be done)04在线用户展示---仅仅从Redis取一下数据做展示,查看若依存储的资料,用RDM
网页设计,若依项目修改(It must be done)04在线用户展示---仅仅从Redis取一下数据做展示,查看若依存储的资料,用RDM
|
19天前
|
存储 缓存 NoSQL
Redis为什么速度快:数据结构、存储及IO网络原理总结
Redis为什么速度快:数据结构、存储及IO网络原理总结
|
24天前
|
存储 NoSQL Redis
Redis系列-存储hash主要操作命令
Redis系列-存储hash主要操作命令
|
11天前
|
小程序 开发者
uniapp实战 —— 开发微信小程序的调试技巧
uniapp实战 —— 开发微信小程序的调试技巧
14 1
|
11天前
|
小程序
【微信小程序-原生开发】富文本编辑器 editor 的使用教程
【微信小程序-原生开发】富文本编辑器 editor 的使用教程
18 0
【微信小程序-原生开发】富文本编辑器 editor 的使用教程
|
11天前
|
存储 小程序 API
【微信小程序-原生开发+云开发+TDesign】修改用户头像(含wx.chooseMedia,wx.cloud.uploadFile,wx.cloud.deleteFile的使用)
【微信小程序-原生开发+云开发+TDesign】修改用户头像(含wx.chooseMedia,wx.cloud.uploadFile,wx.cloud.deleteFile的使用)
10 0
【微信小程序-原生开发+云开发+TDesign】修改用户头像(含wx.chooseMedia,wx.cloud.uploadFile,wx.cloud.deleteFile的使用)