Model.count with params support, fix time in mysql

This commit is contained in:
Anatoliy Chakkaev 2012-01-30 17:27:26 +04:00
parent b237b7bd4c
commit ad7d1d568a
8 changed files with 149 additions and 46 deletions

View File

@ -243,8 +243,12 @@ AbstractClass.destroyAll = function destroyAll(cb) {
}.bind(this));
};
AbstractClass.count = function (cb) {
this.schema.adapter.count(this.modelName, cb);
AbstractClass.count = function (where, cb) {
if (typeof where === 'function') {
cb = where;
where = null;
}
this.schema.adapter.count(this.modelName, cb, where);
};
AbstractClass.toString = function () {

View File

@ -119,8 +119,21 @@ Memory.prototype.destroyAll = function destroyAll(model, callback) {
callback();
};
Memory.prototype.count = function count(model, callback) {
callback(null, Object.keys(this.cache[model]).length);
Memory.prototype.count = function count(model, callback, where) {
var cache = this.cache[model];
var data = Object.keys(cache)
if (where) {
data = data.filter(function (id) {
var ok = true;
Object.keys(where).forEach(function (key) {
if (cache[id][key] != where[key]) {
ok = false;
}
});
return ok;
});
}
callback(null, data.length);
};
Memory.prototype.updateAttributes = function updateAttributes(model, id, data, cb) {

View File

@ -15,7 +15,8 @@ exports.initialize = function initializeSchema(schema, callback) {
});
schema.adapter = new MySQL(schema.client);
process.nextTick(callback);
schema.client.query('SET TIME_ZONE = "+04:00"', callback);
// process.nextTick(callback);
};
function MySQL(client) {
@ -77,6 +78,19 @@ MySQL.prototype.toFields = function (model, data) {
return fields.join(',');
};
function dateToMysql(val) {
return val.getUTCFullYear() + '-' +
fillZeros(val.getUTCMonth() + 1) + '-' +
fillZeros(val.getUTCDate()) + ' ' +
fillZeros(val.getUTCHours()) + ':' +
fillZeros(val.getUTCMinutes()) + ':' +
fillZeros(val.getUTCSeconds());
function fillZeros(v) {
return v < 10 ? '0' + v : v;
}
}
MySQL.prototype.toDatabase = function (prop, val) {
if (prop.type.name === 'Number') return val;
if (val === null) return 'NULL';
@ -85,15 +99,7 @@ MySQL.prototype.toDatabase = function (prop, val) {
if (!val.toUTCString) {
val = new Date(val);
}
val = [
val.getFullYear(),
val.getMonth() + 1,
val.getDate(),
val.getHours(),
val.getMinutes(),
val.getSeconds()
].join('-');
return '"' + val + '"';
return '"' + dateToMysql(val) + '"';
}
if (prop.type.name == "Boolean") return val ? 1 : 0;
return this.client.escape(val.toString());
@ -105,7 +111,9 @@ MySQL.prototype.fromDatabase = function (model, data) {
Object.keys(data).forEach(function (key) {
var val = data[key];
if (props[key]) {
// if (props[key])
if (props[key].type.name === 'Date') {
val = new Date(val.toString().replace(/GMT.*$/, 'GMT'));
}
}
data[key] = val;
});
@ -165,7 +173,9 @@ MySQL.prototype.all = function all(model, filter, callback) {
if (err) {
return callback(err, []);
}
callback(null, data);
callback(null, data.map(function (obj) {
return self.fromDatabase(model, obj);
}));
}.bind(this));
return sql;
@ -203,10 +213,26 @@ MySQL.prototype.destroyAll = function destroyAll(model, callback) {
}.bind(this));
};
MySQL.prototype.count = function count(model, callback) {
this.query('SELECT count(*) as cnt FROM ' + model, function (err, res) {
MySQL.prototype.count = function count(model, callback, where) {
var self = this;
var props = this._models[model].properties;
this.query('SELECT count(*) as cnt FROM ' + model + buildWhere(where), function (err, res) {
callback(err, err ? null : res[0].cnt);
});
function buildWhere(conds) {
var cs = [];
Object.keys(conds || {}).forEach(function (key) {
var keyEscaped = '`' + key.replace(/\./g, '`.`') + '`'
if (conds[key] === null) {
cs.push(keyEscaped + ' IS NULL');
} else {
cs.push(keyEscaped + ' = ' + self.toDatabase(props[key], conds[key]));
}
});
return cs.length ? ' WHERE ' + cs.join(' AND ') : '';
}
};
MySQL.prototype.updateAttributes = function updateAttrs(model, id, data, cb) {

View File

@ -254,10 +254,21 @@ Neo4j.prototype.destroy = function destroy(model, id, callback) {
Neo4j.prototype.all = function all(model, filter, callback) {
this.client.queryNodeIndex(model, 'id:*', function (err, nodes) {
if (nodes) {
nodes = nodes.map(function (s) { s.data.id = s.id; return s.data });
nodes = nodes.map(function (obj) {
obj.data.id = obj.id;
return this.readFromDb(model, obj.data);
}.bind(this));
}
callback(err, filter && nodes ? nodes.filter(applyFilter(filter)) : nodes);
if (filter) {
nodes = nodes ? nodes.filter(applyFilter(filter)) : nodes;
if (filter.order) {
nodes = nodes.sort(function (a, b) {
return a[filter.order] > b[filter.order];
});
}
}
callback(err, nodes);
}.bind(this));
};
Neo4j.prototype.allNodes = function all(model, callback) {
@ -285,6 +296,10 @@ function applyFilter(filter) {
if (typeof value === 'string' && example && example.constructor.name === 'RegExp') {
return value.match(example);
}
if (typeof value === 'object' && value.constructor.name === 'Date' && typeof example === 'object' && example.constructor.name === 'Date') {
return example.toString() === value.toString();
}
console.log(example,'==', value, example == value);
// not strict equality
return example == value;
}
@ -308,8 +323,8 @@ Neo4j.prototype.destroyAll = function destroyAll(model, callback) {
}
};
Neo4j.prototype.count = function count(model, callback) {
this.all(model, null, function (err, collection) {
Neo4j.prototype.count = function count(model, callback, conds) {
this.all(model, {where: conds}, function (err, collection) {
callback(err, collection ? collection.length : 0);
});
};

View File

@ -93,6 +93,22 @@ PG.prototype.toFields = function (model, data, forCreate) {
}
};
function dateToPostgres(val) {
return [
val.getUTCFullYear(),
fz(val.getUTCMonth() + 1),
fz(val.getUTCDate())
].join('-') + ' ' + [
fz(val.getUTCHours()),
fz(val.getUTCMinutes()),
fz(val.getUTCSeconds())
].join(':');
function fz(v) {
return v < 10 ? '0' + v : v;
}
}
PG.prototype.toDatabase = function (prop, val) {
if (val === null) return 'NULL';
if (prop.type.name === 'Number') return val;
@ -101,18 +117,10 @@ PG.prototype.toDatabase = function (prop, val) {
if (!val.toUTCString) {
val = new Date(val);
}
val = [
val.getUTCFullYear(),
val.getUTCMonth() + 1,
val.getUTCDate()
].join('-') + ' ' + [
val.getUTCHours(),
val.getUTCMinutes(),
val.getUTCSeconds()
].join(':');
return escape(val);
return escape(dateToPostgres(val));
}
return escape(val.toString());
};
PG.prototype.fromDatabase = function (model, data) {
@ -161,7 +169,7 @@ PG.prototype.all = function all(model, filter, callback) {
if (err) {
return callback(err, []);
}
callback(err, filter ? data.items.filter(applyFilter(filter)) : data.items);
callback(err, filter && filter.where ? data.items.filter(applyFilter(filter)) : data.items);
}.bind(this));
};
@ -171,7 +179,7 @@ PG.prototype.toFilter = function (model, filter) {
}
if (!filter) return '';
var props = this._models[model].properties;
var out='';
var out = '';
if (filter.where) {
var fields = [];
Object.keys(filter.where).forEach(function (key) {
@ -188,9 +196,18 @@ PG.prototype.toFilter = function (model, filter) {
}
}.bind(this));
if (fields.length) {
out += ' where ' + fields.join(' AND ');
out += ' WHERE ' + fields.join(' AND ');
}
}
if (filter.order) {
out += ' ORDER BY ' + filter.order;
}
if (filter.limit) {
out += ' LIMIT ' + filter.limit + ' ' + (filter.offset || '');
}
return out;
};
@ -228,11 +245,26 @@ PG.prototype.destroyAll = function destroyAll(model, callback) {
}.bind(this));
};
PG.prototype.count = function count(model, callback) {
this.query('SELECT count(*) as cnt FROM "' + model + '"', function (err, res) {
PG.prototype.count = function count(model, callback, where) {
var self = this;
var props = this._models[model].properties;
this.query('SELECT count(*) as cnt FROM "' + model + '"' + buildWhere(where), function (err, res) {
if (err) return callback(err);
callback(err, res && res.items[0] && res.items[0].cnt);
});
function buildWhere(conds) {
var cs = [];
Object.keys(conds || {}).forEach(function (key) {
if (conds[key] === null) {
cs.push(key + ' IS NULL');
} else {
cs.push(key + ' = ' + self.toDatabase(props[key], conds[key]));
}
});
return cs.length ? ' WHERE ' + cs.join(' AND ') : '';
}
};
PG.prototype.updateAttributes = function updateAttrs(model, id, data, cb) {

View File

@ -366,13 +366,19 @@ BridgeToRedis.prototype.destroyAll = function destroyAll(model, callback) {
}.bind(this));
};
BridgeToRedis.prototype.count = function count(model, callback) {
BridgeToRedis.prototype.count = function count(model, callback, where) {
var keysQuery = model + ':*';
var t1 = Date.now();
if (where && Object.keys(where).length) {
this.all(model, {where: where}, function (err, data) {
callback(err, err ? null : data.length);
});
} else {
this.client.keys(keysQuery, function (err, keys) {
this.log('KEYS ' + keysQuery, t1);
callback(err, err ? null : keys.length);
}.bind(this));
}
};
BridgeToRedis.prototype.updateAttributes = function updateAttrs(model, id, data, cb) {

View File

@ -8,7 +8,7 @@
},
"main": "index.js",
"scripts": {
"test": "ONLY=memory ./support/nodeunit/bin/nodeunit test/*_test.* && ONLY=redis nodeunit test/common_test.js && ONLY=mysql nodeunit test/common_test.js"
"test": "ONLY=memory ./support/nodeunit/bin/nodeunit test/*_test.* && ONLY=redis nodeunit test/common_test.js && ONLY=mysql nodeunit test/common_test.js && ONLY=postgres nodeunit test/common_test.js"
},
"engines": [
"node >= 0.4.0"

View File

@ -297,12 +297,15 @@ function testOrm(schema) {
});
});
var countOfposts;
var countOfposts, countOfpostsFiltered;
it('should fetch collection', function (test) {
Post.all(function (err, posts) {
countOfposts = posts.length;
test.ok(countOfposts > 0);
test.ok(posts[0] instanceof Post);
countOfpostsFiltered = posts.filter(function (p) {
return p.title === 'title';
}).length;
test.done();
});
});
@ -310,9 +313,12 @@ function testOrm(schema) {
it('should fetch count of records in collection', function (test) {
Post.count(function (err, count) {
test.equal(countOfposts, count);
Post.count({title: 'title'}, function (err, count) {
test.equal(countOfpostsFiltered, count);
test.done();
});
});
});
it('should find filtered set of records', function (test) {
var wait = 3;
@ -481,6 +487,7 @@ function testOrm(schema) {
if (err) console.log(err);
test.equal(posts.length, 5);
dates.sort(numerically).forEach(function (d, i) {
// fix inappropriated tz convert
test.equal(posts[i].date.toString(), d.toString());
});
finished();