在传统的项目中,我们经常会用到缓存来优化数据库的读取,比如java中,我们利用spring的AOP能力,在读写数据库前增加对缓存的操作。

在node与mongodb的项目中也仍然会存在类似问题,本文参考了mongoose-redis-cache这个插件。

https://github.com/conancat/mongoose-redis-cache

该插件还不太完善,但基本的思路是很简单的,初始化一个redis客户端,然后重写mongoose的exec方法,将exec的参数设置为redis的key,将数据库返回的结果设置为对应的value。

每次操作时优先读取redis。

代码如下:

// Generated by CoffeeScript 1.5.0
var mongooseRedisCache, redis, _; redis = require("redis"); _ = require("underscore"); mongooseRedisCache = function(mongoose, options, callback) {
var client, host, pass, port, redisOptions;
if (options == null) {
options = {};
}
host = options.host || "";
port = options.port || "";
pass = options.pass || "";
redisOptions = options.options || {};
mongoose.redisClient = client = redis.createClient(port, host, redisOptions);
if (pass.length > 0) {
client.auth(pass, function(err) {
if (callback) {
return callback(err);
}
});
}

//这里做了改动,原来是execFind,在我当前的Mongoose版本下无法使用
mongoose.Query.prototype._exec = mongoose.Query.prototype.exec;
mongoose.Query.prototype.exec = function(callback) { var cb, expires, fields, key, model, query, schemaOptions, self;
self = this;
model = this.model;
query = this._conditions;
options = this._optionsForExec(model);
fields = _.clone(this._fields);
schemaOptions = model.schema.options;
expires = schemaOptions.expires || 60; if (!schemaOptions.redisCache && options.lean) {
return mongoose.Query.prototype._exec.apply(self, arguments);
}
key = JSON.stringify(query) + JSON.stringify(options) + JSON.stringify(fields); cb = function(err, result) {
var docs;
if (err) {
return callback(err);
}
if (!result) {
return mongoose.Query.prototype._exec.call(self, function(err, docs) {
var str;
if (err) {
return callback(err);
}
str = JSON.stringify(docs);
client.set(key, str);
client.expire(key, expires);
return callback(null, docs);
});
} else {
docs = JSON.parse(result);
return callback(null, docs);
}
};
client.get(key, cb);
return this;
};
}; module.exports = mongooseRedisCache;

写测试用例如下:

var mongoose = require('mongoose');

var async = require('async');
var mongooseRedisCache = require("mongoose-redis-cache");
mongooseRedisCache(mongoose);
var Schema = mongoose.Schema; mongoose.connect('mongodb://localhost/cachetest'); var user = new Schema({
username:{
type:String,
index:true
},
password:String
}); user.set('redisCache', true); var userModel = mongoose.model('user', user); var entity = new userModel({
username:'fredric',
password:'sinny'
}); var users = [];
for(var i = 0; i < 1000; i++){
users.push({
username:'fredric' + i,
password:'sinny' + i
});
} function testCache(){ function datainit(item,cb){
var entity = new userModel(item);
entity.save(function(err){
cb(err);
});
} async.mapSeries(users, datainit, function(err, results){ console.log('datainit finished'); var timestamp = new Date().valueOf(); var round = [];
for(var i = 0; i < 2000; i++){
round.push(i);
} //利用缓存
function test(item,cb){
query = userModel.find({'username':'fredric101'});
query.lean();
query.exec(function(err, result){
cb(err);
});
} //不利用缓存
function test_nocache(item,cb){
query = userModel.find({}).setOptions({nocache: true});
query.where("username", "fredric101");
query.exec(function(err, result){
cb(err);
});
} async.mapSeries(round, test_nocache, function(err, results){
console.log(new Date().valueOf() - timestamp);
});
});
}
testCache();

测试结果还是比较明显的,在我本地笔记本上(安装redis + mongodb),上述测试用例执行:

1、无缓存、无索引:21501ms

2、无缓存、有索引:1966ms

3、有缓存、有索引:281ms

mongodb(mongoose-redis-cache)的更多相关文章

  1. 现在 做java 构架(RabbitMQ redis mysql )之类的

    现在 做java 构架(RabbitMQ redis mysql )之类的

  2. mongoDB (mongoose、增删改查、聚合、索引、连接、备份与恢复、监控等等)

    MongoDB - 简介 官网:https://www.mongodb.com/ MongoDB 是一个基于分布式文件存储的数据库,由 C++ 语言编写,旨在为 WEB 应用提供可扩展的高性能数据存储 ...

  3. HTTP协议(缓存机制Cache)

    HTTP的缓存 至于响应消息的实体,与请求消息的实体内容相似,这里只借绍下User-Agent头 User-Agent头域的内容包含发出请求的用户信息. Cache-Control头域(请求和应答通用 ...

  4. MongoDB(课时29 MapReduce)

    3.7.4 MapReduce MapReduce 是整个大数据的精髓所在(实际中别用,因为在MongoDB中属于最底层操作). MapReduce是一种计算模型,简单的说就是将大批量的工作分解执行, ...

  5. MongoDB(课时24 全文索引)

    3.6.3 全文索引 在一些信息管理平台上经常需要进行信息模糊查询,最早的时候是利用了某个字段上实现的模糊查询,但这个时候返回的信息并不会很准确,因为只能够查A字段或B字段,而在MongoDB里面实现 ...

  6. MongoDB(课时17 更新函数)

    3.4.3 数据更新操作 MongoDB数据存的是副本数据, 最终的数据还要保存在传统的数据库里,所以如果关系型数据库里数据变了,最好的方法是删除里面的MongoDB数据重新插入. 在MongoDB里 ...

  7. NoSQL高级培训课程-HBase&&MongoDB(两天版)

    课程大纲 主题 时间 主题 列数据库 (第1天) 上午 HBase发展简史-Google BigTable的开源实现 HBase基础:安装部署.管理命令.运行监控和开发接口: HBase专题:服务组件 ...

  8. Debian Buster 配置 Laravel 运行环境(nginx + redis + supervisor)

    1 目标 将开发完成的 Laravel 项目布署于 Debian 之上.由于项目要求使用 horizon 官方扩展,要求 PHP7.1+,故采用 Debian buster (下一版) 2 材料 IP ...

  9. 配置到 Framework GAC(Global Assembly Cache) Assembly

    配置到 Framework 通常有两种方法,一种是直接把它放到GAC(Global Assembly Cache作用是可以存放一些有很多程序都要用到的公共Assembly)中 :另一种是把它们放到具体 ...

  10. MongoDB(课时7 逻辑运算)

    3.4.2.2 逻辑运算 逻辑运算主要三种类型:与($and),或($or),非($not.$nor). 范例:查询年龄在20~21岁的学生信息 db.students.find({"age ...

随机推荐

  1. oracle 密码过期处理

    1.查看用户的proifle是哪个,一般是default sql>SELECT username,PROFILE FROM dba_users; 2.查看指定概要文件(如default)的密码有 ...

  2. Verilog经典输入控制/激励信号模板1

    :]i;   always @ ( posedge CLOCK or negedge RESET )  if( !RESET ) begin  i <= 'd0;  Start_Si ...

  3. jekyll安装的斗智斗勇

    jekyll---将纯文本转化为静态网站和博客,GitHub Pages 可以运行 Jekyll,你很简单就可以完全免费的在 GitHub 上发布网站. 小白安装jekyll时的若干问题,有错误欢迎指 ...

  4. Number()数据类型转换

    Number() 如果是 Boolean 值, 和.如果是数字值,只是简单的传入和返回.如果是 .如果是 undefined,返回NaN. 如果是字符串,遵循下列规则:    如果字符串中只包含数字( ...

  5. NetSuite API - SuiteScript API.js

    /* from: http://blog.csdn.net/levin_rain/article/details/8571444 */ ' Core SuiteScript Functions ' f ...

  6. TYVJ博弈论

    一些比较水的博弈论...(为什么都没有用到那什么SG呢....) TYVJ 1140  飘飘乎居士拯救MM 题解: 歌德巴赫猜想 #include <cmath> #include < ...

  7. 18.safari 安装后flash还是提示安装 flash,视频不能播放

    第一步: safari---->偏好设置(首先安装最新Mac adobe flash) 第二步: 第三步:点击进入 第四步:再次打开safar,大功告成!

  8. linux下安装oracle

    一>1.关闭防火墙,禁用selinux vi /etc/selinux/config  修改SELINUX=disabled,然后重启,如果不想重启使用命令setenforce 0 2.安装依赖 ...

  9. Web前端学习路线

    第一阶段: HTML+CSS:HTML进阶.CSS进阶.div+css布局.HTML+css整站开发. JavaScript基础:Js基础教程.js内置对象常用方法.常见DOM树操作大全.ECMAsc ...

  10. 关于mock server

    这篇技术博客是在知乎上看到的 知乎js大神张云龙写的 这里贴过来记录下,如果侵权 请告知将及时删除. --------------------------- 为了更好的分工合作,让前端能在不依赖后端环 ...