From 76b8bf54d15681dd971fea1281dfa57039da8327 Mon Sep 17 00:00:00 2001 From: Anatoliy Chakkaev Date: Wed, 5 Oct 2011 00:17:06 +0400 Subject: [PATCH] Indexes in redis --- lib/redis.js | 73 ++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/lib/redis.js b/lib/redis.js index 2fd3ca86..56224555 100644 --- a/lib/redis.js +++ b/lib/redis.js @@ -18,18 +18,54 @@ exports.initialize = function initializeSchema(schema, callback) { function BridgeToRedis(client) { this._models = {}; this.client = client; + this.indexes = {}; } BridgeToRedis.prototype.define = function (descr) { - this._models[descr.model.modelName] = descr; + var m = descr.model.modelName; + this._models[m] = descr; + this.indexes[m] = {}; + Object.keys(descr.properties).forEach(function (prop) { + if (descr.properties[prop].index) { + this.indexes[m][prop] = descr.properties[prop].type; + } + }.bind(this)); +}; + +BridgeToRedis.prototype.defineForeignKey = function (model, key, cb) { + this.indexes[model][key] = Number; + cb(null, Number); }; BridgeToRedis.prototype.save = function (model, data, callback) { - this.client.hmset(model + ':' + data.id, data, callback); + this.client.hmset(model + ':' + data.id, data, function (err) { + if (err) return callback(err); + this.updateIndexes(model, data, callback); + }.bind(this)); +}; + +BridgeToRedis.prototype.updateIndexes = function (model, data, callback) { + var i = this.indexes[model]; + var schedule = []; + Object.keys(data).forEach(function (key) { + if (i[key]) { + schedule.push([ + 'sadd', + 'i:' + model + ':' + key + ':' + data[key], + model + ':' + data.id + ]); + } + }.bind(this)); + + if (schedule.length) { + this.client.multi(schedule).exec(callback); + } else { + callback(null); + } }; BridgeToRedis.prototype.create = function (model, data, callback) { - this.client.incr(model + ':id', function (err, id) { + this.client.incr('id:' + model, function (err, id) { data.id = id; this.save(model, data, function (err) { if (callback) { @@ -64,8 +100,34 @@ BridgeToRedis.prototype.destroy = function destroy(model, id, callback) { }); }; +BridgeToRedis.prototype.possibleIndex = function possibleIndex(model, filter) { + if (!filter || Object.keys(filter).length === 0) return false; + + var foundIndex = false; + Object.keys(filter).forEach(function (key) { + if (!foundIndex && this.indexes[model][key]) { + foundIndex = key; + } + }.bind(this)); + + return foundIndex; +}; + BridgeToRedis.prototype.all = function all(model, filter, callback) { - this.client.keys(model + ':*', function (err, keys) { + var ts = Date.now(); + + var index = this.possibleIndex(model, filter); + if (false) { + // console.log('using index!', filter); + this.client.smembers('i:' + model + ':' + index + ':' + filter[index], + handleKeys.bind(this)); + } else { + // console.log('without index', filter); + this.client.keys(model + ':*', handleKeys.bind(this)); + } + + function handleKeys(err, keys) { + // console.log(arguments); if (err) { return callback(err, []); } @@ -73,9 +135,10 @@ BridgeToRedis.prototype.all = function all(model, filter, callback) { return ['hgetall', key]; }); this.client.multi(query).exec(function (err, replies) { + // console.log('Redis time: %dms', Date.now() - ts); callback(err, filter ? replies.filter(applyFilter(filter)) : replies); }); - }.bind(this)); + } }; function applyFilter(filter) {