Move conditions to `where` section, fix neo4j

This commit is contained in:
Anatoliy Chakkaev 2011-11-04 14:30:25 +07:00
parent 775b6b8b1c
commit b5985e445d
9 changed files with 84 additions and 44 deletions

View File

@ -144,17 +144,27 @@ AbstractClass.find = function find(id, cb) {
}.bind(this));
};
AbstractClass.all = function all(filter, cb) {
/**
* Query collection of objects
* @param params {where: {}, order: '', limit: 1, offset: 0,...}
* @param cb (err, array of AbstractClass)
*/
AbstractClass.all = function all(params, cb) {
if (arguments.length === 1) {
cb = filter;
filter = null;
cb = params;
params = null;
}
var constr = this;
this.schema.adapter.all(this.modelName, filter, function (err, data) {
this.schema.adapter.all(this.modelName, params, function (err, data) {
var collection = null;
if (data && data.map) {
collection = data.map(function (d) {
var obj = null;
// really questionable stuff
// goal is obvious: to not create different instances for the same object
// but the way it implemented...
// we can lost some dirty state of object, for example
// TODO: think about better implementation, test keeping dirty state
if (constr.cache[d.id]) {
obj = constr.cache[d.id];
constr.call(obj, d);
@ -314,7 +324,7 @@ AbstractClass.hasMany = function (anotherClass, params) {
defineScope(this.prototype, anotherClass, methodName, function () {
var x = {};
x[fk] = this.id;
return x;
return {where: x};
}, {
find: find,
destroy: destroy
@ -402,7 +412,7 @@ function defineScope(class, targetClass, name, params, methods) {
throw new Error('Method only can be called with one or two arguments');
}
return targetClass.all(merge(actualCond, caller._scope), cb);
return targetClass.all(mergeParams(actualCond, caller._scope), cb);
};
f._scope = typeof params === 'function' ? params.call(this) : params;
f.build = build;
@ -417,7 +427,7 @@ function defineScope(class, targetClass, name, params, methods) {
Object.defineProperty(f, name, {
enumerable: false,
get: function () {
merge(f._scope, targetClass._scopeMeta[name]);
mergeParams(f._scope, targetClass._scopeMeta[name]);
return f;
}
});
@ -429,7 +439,7 @@ function defineScope(class, targetClass, name, params, methods) {
// and it should have create/build methods with binded thisModelNameId param
function build(data) {
data = data || {};
return new targetClass(merge(this._scope, data));
return new targetClass(mergeParams(this._scope, {where:data}).where);
}
function create(data, cb) {
@ -443,6 +453,20 @@ function defineScope(class, targetClass, name, params, methods) {
function destroyAll(id, cb) {
// implement me
}
function mergeParams(base, update) {
if (update.where) {
base.where = merge(base.where, update.where);
}
// overwrite order
if (update.order) {
base.order = update.order;
}
return base;
}
}
// helper methods

View File

@ -50,14 +50,14 @@ Memory.prototype.all = function all(model, filter, callback) {
};
function applyFilter(filter) {
if (typeof filter === 'function') {
return filter;
if (typeof filter.where === 'function') {
return filter.where;
}
var keys = Object.keys(filter);
var keys = Object.keys(filter.where);
return function (obj) {
var pass = true;
keys.forEach(function (key) {
if (!test(filter[key], obj[key])) {
if (!test(filter.where[key], obj[key])) {
pass = false;
}
});

View File

@ -88,7 +88,10 @@ MongooseAdapter.prototype.destroy = function destroy(model, id, callback) {
};
MongooseAdapter.prototype.all = function all(model, filter, callback) {
this._models[model].find(typeof filter === 'function' ? {} : filter, function (err, data) {
if (!filter) {
filter = {};
}
this._models[model].find(typeof filter.where === 'function' ? {} : filter.where, function (err, data) {
if (err) return callback(err);
callback(null, data);
});

View File

@ -122,6 +122,7 @@ MySQL.prototype.destroy = function destroy(model, id, callback) {
});
};
// TODO: hook up where, order, limit and offset conditions
MySQL.prototype.all = function all(model, filter, callback) {
this.client.query('SELECT * FROM ' + model, function (err, data) {
if (err) {
@ -132,14 +133,14 @@ MySQL.prototype.all = function all(model, filter, callback) {
};
function applyFilter(filter) {
if (typeof filter === 'function') {
if (typeof filter.where === 'function') {
return filter;
}
var keys = Object.keys(filter);
var keys = Object.keys(filter.where);
return function (obj) {
var pass = true;
keys.forEach(function (key) {
if (!test(filter[key], obj[key])) {
if (!test(filter.where[key], obj[key])) {
pass = false;
}
});

View File

@ -146,7 +146,9 @@ Neo4j.prototype.node = function find(id, callback) {
callback(null, this.cache[id]);
} else {
this.client.getNodeById(id, function (err, node) {
this.cache[id] = node;
if (node) {
this.cache[id] = node;
}
callback(err, node);
}.bind(this));
}
@ -156,6 +158,7 @@ Neo4j.prototype.create = function create(model, data, callback) {
data.nodeType = model;
var node = this.client.createNode();
node.data = cleanup(data);
node.data.nodeType = model;
node.save(function (err) {
if (err) {
return callback(err);
@ -250,21 +253,27 @@ 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) { return s.data });
nodes = nodes.map(function (s) { s.data.id = s.id; return s.data });
}
callback(err, filter && nodes ? nodes.filter(applyFilter(filter)) : nodes);
});
};
Neo4j.prototype.allNodes = function all(model, callback) {
this.client.queryNodeIndex(model, 'id:*', function (err, nodes) {
callback(err, nodes);
});
};
function applyFilter(filter) {
if (typeof filter === 'function') {
return filter;
if (typeof filter.where === 'function') {
return filter.where;
}
var keys = Object.keys(filter);
var keys = Object.keys(filter.where || {});
return function (obj) {
var pass = true;
keys.forEach(function (key) {
if (!test(filter[key], obj.data[key])) {
if (!test(filter.where[key], obj[key])) {
pass = false;
}
});
@ -282,7 +291,7 @@ function applyFilter(filter) {
Neo4j.prototype.destroyAll = function destroyAll(model, callback) {
var wait, error = null;
this.all(model, null, function (err, collection) {
this.allNodes(model, function (err, collection) {
if (err) return callback(err);
wait = collection.length;
collection && collection.forEach && collection.forEach(function (node) {

View File

@ -103,12 +103,12 @@ BridgeToRedis.prototype.destroy = function destroy(model, id, callback) {
};
BridgeToRedis.prototype.possibleIndexes = function (model, filter) {
if (!filter || Object.keys(filter).length === 0) return false;
if (!filter || Object.keys(filter.where).length === 0) return false;
var foundIndex = [];
Object.keys(filter).forEach(function (key) {
if (this.indexes[model][key] && typeof filter[key] === 'string') {
foundIndex.push('i:' + model + ':' + key + ':' + filter[key]);
Object.keys(filter.where).forEach(function (key) {
if (this.indexes[model][key] && typeof filter.where[key] === 'string') {
foundIndex.push('i:' + model + ':' + key + ':' + filter.where[key]);
}
}.bind(this));
@ -142,14 +142,14 @@ BridgeToRedis.prototype.all = function all(model, filter, callback) {
};
function applyFilter(filter) {
if (typeof filter === 'function') {
return filter;
if (typeof filter.where === 'function') {
return filter.where;
}
var keys = Object.keys(filter);
var keys = Object.keys(filter.where);
return function (obj) {
var pass = true;
keys.forEach(function (key) {
if (!test(filter[key], obj[key])) {
if (!test(filter.where[key], obj[key])) {
pass = false;
}
});

View File

@ -158,14 +158,14 @@ SequelizeAdapter.prototype.all = function all(model, filter, callback) {
};
function applyFilter(filter) {
if (typeof filter === 'function') {
return filter;
if (typeof filter.where === 'function') {
return filter.where;
}
var keys = Object.keys(filter);
var keys = Object.keys(filter.where || {});
return function (obj) {
var pass = true;
keys.forEach(function (key) {
if (!test(filter[key], obj[key])) {
if (!test(filter.where[key], obj[key])) {
pass = false;
}
});

View File

@ -2,7 +2,7 @@
"author": "Anatoliy Chakkaev",
"name": "jugglingdb",
"description": "ORM for every database: redis, mysql, neo4j, mongodb",
"version": "0.0.2",
"version": "0.0.3",
"repository": {
"url": "https://github.com/1602/jugglingdb"
},

View File

@ -158,7 +158,6 @@ function testOrm(schema) {
test.equals(obj.date, date);
Post.find(obj.id, function () {
test.equal(obj.title, title);
console.log(obj.date.toString());
test.equal(obj.date.toString(), date.toString());
test.done();
});
@ -246,7 +245,7 @@ function testOrm(schema) {
var wait = 3;
// exact match with string
Post.all({title: 'New title'}, function (err, res) {
Post.all({where: {title: 'New title'}}, function (err, res) {
var pass = true;
res.forEach(function (r) {
if (r.title != 'New title') pass = false;
@ -257,7 +256,7 @@ function testOrm(schema) {
});
// matching null
Post.all({title: null}, function (err, res) {
Post.all({where: {title: null}}, function (err, res) {
var pass = true;
res.forEach(function (r) {
if (r.title != null) pass = false;
@ -268,7 +267,7 @@ function testOrm(schema) {
});
// matching regexp
Post.all({title: /hello/i}, function (err, res) {
Post.all({where: {title: /hello/i}}, function (err, res) {
var pass = true;
res.forEach(function (r) {
if (!r.title || !r.title.match(/hello/i)) pass = false;
@ -294,7 +293,7 @@ function testOrm(schema) {
test.ok(u.posts.create, 'Method defined: posts.create');
u.posts.create(function (err, post) {
if (err) return console.log(err);
test.ok(post.author(), u.id);
// test.ok(post.author(), u.id);
u.posts(function (err, posts) {
test.strictEqual(posts.pop(), post);
test.done();
@ -307,7 +306,7 @@ function testOrm(schema) {
var wait = 2;
test.ok(Post.scope, 'Scope supported');
Post.scope('published', {published: true});
Post.scope('published', {where: {published: true}});
test.ok(typeof Post.published === 'function');
test.ok(Post.published._scope.published = true);
var post = Post.published.build();
@ -323,8 +322,8 @@ function testOrm(schema) {
User.create(function (err, u) {
if (err) return console.log(err);
test.ok(typeof u.posts.published == 'function');
test.ok(u.posts.published._scope.published);
test.equal(u.posts.published._scope.userId, u.id);
test.ok(u.posts.published._scope.where.published);
test.equal(u.posts.published._scope.where.userId, u.id);
done();
});
@ -335,6 +334,10 @@ function testOrm(schema) {
it('should destroy all records', function (test) {
Post.destroyAll(function (err) {
if (err) {
console.log('Error in destroyAll');
throw err;
}
Post.all(function (err, posts) {
test.equal(posts.length, 0);
Post.count(function (err, count) {