在node与mongodb的项目中也仍然会存在类似问题,本文参考了mongoose-redis-cache这个插件。
https://github测试数据/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)
标签:
查看更多关于mongodb(mongoose-redis-cache)的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did160593