diff --git a/.travis.yml b/.travis.yml index ad0eeec0..9e17614b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,6 @@ services: - mongodb - redis-server - neo4j - - couchdb before_install: - git submodule init && git submodule --quiet update - ./support/ci/neo4j.sh @@ -15,4 +14,3 @@ before_script: - "mysql -e 'create database myapp_test;'" - "psql -c 'create database myapp_test;' -U postgres" - mongo mydb_test --eval 'db.addUser("travis", "test");' - - curl -X PUT localhost:5984/myapp_test diff --git a/lib/adapters/mongoose.js b/lib/adapters/mongoose.js index 8b1def20..9d9f2c53 100644 --- a/lib/adapters/mongoose.js +++ b/lib/adapters/mongoose.js @@ -50,13 +50,18 @@ MongooseAdapter.prototype.define = function (descr) { Object.keys(descr.properties).forEach(function (key) { props[key] = {}; props[key].type = descr.properties[key].type; - if (props[key].type.name === 'Text' || props[key].type.name === 'JSON') props[key].type = String; + if (props[key].type.name === 'Text' || props[key].type.name === 'JSON') { + props[key].type = String; + } + if (props[key].type.name === 'Object') { + props[key].type = mongoose.Schema.Types.Mixed; + } if (descr.properties[key].index) { props[key].index = descr.properties[key].index; } }); var schema = new mongoose.Schema(props); - this._models[descr.model.modelName] = mongoose.model(descr.model.modelName, schema); + this._models[descr.model.modelName] = mongoose.model(descr.model.modelName, schema, descr.settings.table || null); this.cache[descr.model.modelName] = {}; }; @@ -160,17 +165,21 @@ MongooseAdapter.prototype.all = function all(model, filter, callback) { }); } if (filter.order) { - var m = filter.order.match(/\s+(A|DE)SC$/); - var key = filter.order; - var reverse = false; - if (m) { - key = key.replace(/\s+(A|DE)SC$/, ''); - if (m[1] === 'DE') reverse = true; + var keys = filter.order; // can be Array or String + if (typeof(keys) == "string") { + keys = keys.split(','); } - if (reverse) { - query.sort('-' + key); - } else { - query.sort(key); + var args = []; + + for(index in keys) { + var m = keys[index].match(/\s+(A|DE)SC$/); + + keys[index] = keys[index].replace(/\s+(A|DE)SC$/, ''); + if (m && m[1] === 'DE') { + query.sort(keys[index].trim(), -1); + } else { + query.sort(keys[index].trim(), 1); + } } } if (filter.limit) { diff --git a/test/common_test.js b/test/common_test.js index 68dc519d..f250e6d1 100644 --- a/test/common_test.js +++ b/test/common_test.js @@ -71,11 +71,13 @@ function testOrm(schema) { joinedAt: Date, age: Number, passwd: { type: String, index: true }, - settings: { type: Schema.JSON } + settings: { type: Schema.JSON }, + extra: Object }); Post = schema.define('Post', { title: { type: String, length: 255, index: true }, + subject: { type: String }, content: { type: Text }, date: { type: Date, default: function () { return new Date }, index: true }, published: { type: Boolean, default: false }, @@ -162,7 +164,7 @@ function testOrm(schema) { it('should be expoted to JSON', function (test) { test.equal(JSON.stringify(new Post({id: 1, title: 'hello, json', date: 1})), - '{"id":1,"title":"hello, json","content":null,"date":1,"published":false,"likes":[],"related":[],"userId":null}'); + '{"id":1,"title":"hello, json","subject":null,"content":null,"date":1,"published":false,"likes":[],"related":[],"userId":null}'); test.done(); }); @@ -496,16 +498,23 @@ function testOrm(schema) { }); it('should handle ORDER clause', function (test) { - var titles = [ 'Title A', 'Title Z', 'Title M', 'Title B', 'Title C' ]; - var dates = [ + var titles = [ { title: 'Title A', subject: "B" }, + { title: 'Title Z', subject: "A" }, + { title: 'Title M', subject: "C" }, + { title: 'Title A', subject: "A" }, + { title: 'Title B', subject: "A" }, + { title: 'Title C', subject: "D" }]; + var isRedis = Post.schema.name === 'redis' || Post.schema.name === 'memory'; + var dates = isRedis ? [ 5, 9, 0, 17, 10, 9 ] : [ new Date(1000 * 5 ), new Date(1000 * 9), new Date(1000 * 0), new Date(1000 * 17), + new Date(1000 * 10), new Date(1000 * 9) ]; titles.forEach(function (t, i) { - Post.create({title: t, date: dates[i]}, done); + Post.create({title: t.title, subject: t.subject, date: dates[i]}, done); }); var i = 0, tests = 0; @@ -515,18 +524,29 @@ function testOrm(schema) { doFilterAndSortReverseTest(); doStringTest(); doNumberTest(); + + if (schema.name == 'mongoose') { + doMultipleSortTest(); + doMultipleReverseSortTest(); + } } } + function compare(a, b) { + if (a.title < b.title) return -1; + if (a.title > b.title) return 1; + return 0; + } + // Post.schema.log = console.log; function doStringTest() { tests += 1; Post.all({order: 'title'}, function (err, posts) { if (err) console.log(err); - test.equal(posts.length, 5); - titles.sort().forEach(function (t, i) { - if (posts[i]) test.equal(posts[i].title, t, 'doStringTest'); + test.equal(posts.length, 6); + titles.sort(compare).forEach(function (t, i) { + if (posts[i]) test.equal(posts[i].title, t.title); }); finished(); }); @@ -536,7 +556,7 @@ function testOrm(schema) { tests += 1; Post.all({order: 'date'}, function (err, posts) { if (err) console.log(err); - test.equal(posts.length, 5); + test.equal(posts.length, 6); dates.sort(numerically).forEach(function (d, i) { if (posts[i]) test.equal(posts[i].date.toString(), d.toString(), 'doNumberTest'); @@ -573,6 +593,34 @@ function testOrm(schema) { }); } + function doMultipleSortTest() { + tests += 1; + Post.all({order: "title ASC, subject ASC"}, function(err, posts) { + if (err) console.log(err); + test.equal(posts.length, 6); + test.equal(posts[0].title, "Title A"); + test.equal(posts[0].subject, "A"); + test.equal(posts[1].title, "Title A"); + test.equal(posts[1].subject, "B"); + test.equal(posts[5].title, "Title Z"); + finished(); + }); + } + + function doMultipleReverseSortTest() { + tests += 1; + Post.all({order: "title ASC, subject DESC"}, function(err, posts) { + if (err) console.log(err); + test.equal(posts.length, 6); + test.equal(posts[0].title, "Title A"); + test.equal(posts[0].subject, "B"); + test.equal(posts[1].title,"Title A"); + test.equal(posts[1].subject, "A"); + test.equal(posts[5].title, "Title Z"); + finished(); + }); + } + var fin = 0; function finished() { if (++fin === tests) {