UNPKG

dynamoose

Version:

Dynamoose is a modeling tool for Amazon's DynamoDB (inspired by Mongoose)

728 lines (619 loc) 19.9 kB
'use strict'; var dynamoose = require('../'); dynamoose.AWS.config.update({ accessKeyId: 'AKID', secretAccessKey: 'SECRET', region: 'us-east-1' }); dynamoose.local(); var Schema = dynamoose.Schema; var should = require('should'); describe('Query', function (){ this.timeout(10000); before(function (done) { dynamoose.setDefaults({ prefix: '', suffix: '' }); var dogSchema = new Schema({ ownerId: { type: Number, validate: function(v) { return v > 0; }, hashKey: true, index: [{ global: true, rangeKey: 'color', name: 'ColorRangeIndex', project: true, // ProjectionType: ALL },{ global: true, rangeKey: 'breed', name: 'BreedRangeIndex', project: true, // ProjectionType: ALL }] }, breed: { type: String, required: true, index: { global: true, rangeKey: 'ownerId', name: 'BreedIndex', project: true, // ProjectionType: ALL throughput: 5 // read and write are both 5 } }, origin: { type: String, index: true // name: originLocalIndex, ProjectionType: ALL }, name: { type: String, rangeKey: true, index: true // name: nameLocalIndex, ProjectionType: ALL }, color: { type: String, default: 'Brown', index: [{ // name: colorLocalIndex project: ['name'] // ProjectionType: INCLUDE },{ // name: colorGlobalIndex, no ragne key global: true, project: ['name'] // ProjectionType: INCLUDE }] }, siblings: { type: 'list', list: [ { type: String } ] }, age: { type: Number } }); var Dog = dynamoose.model('Dog', dogSchema); function addDogs (dogs) { if(dogs.length <= 0) { return done(); } var dog = new Dog(dogs.pop()); dog.save(function (err) { if (err) { return done(err); } addDogs(dogs); }); } addDogs([ {ownerId:1, name: 'Foxy Lady', breed: 'Jack Russell Terrier', color: 'White, Brown and Black', siblings: ['Quincy', 'Princes'], age: 2}, {ownerId:2, name: 'Quincy', breed: 'Jack Russell Terrier', color: 'White and Brown', siblings: ['Foxy Lady', 'Princes'], age: 3}, {ownerId:2, name: 'Princes', breed: 'Jack Russell Terrier', color: 'White and Brown', siblings: ['Foxy Lady', 'Quincy'], age: 6}, {ownerId:3, name: 'Toto', breed: 'Terrier', color: 'Brown', age: 1}, {ownerId:4, name: 'Oddie', breed: 'beagle', color: 'Tan', age: 2}, {ownerId:5, name: 'Pluto', breed: 'unknown', color: 'Mustard', age: 4}, {ownerId:6, name: 'Brian Griffin', breed: 'unknown', color: 'White', age: 5}, {ownerId:7, name: 'Scooby Doo', breed: 'Great Dane', age: 2}, {ownerId:8, name: 'Blue', breed: 'unknown', color: 'Blue', age: 1}, {ownerId:9, name: 'Lady', breed: ' Cocker Spaniel', age: 6}, {ownerId:10, name: 'Copper', breed: 'Hound', age: 8}, {ownerId:11, name: 'Old Yeller', breed: 'unknown', color: 'Tan', age: 1}, {ownerId:12, name: 'Hooch', breed: 'Dogue de Bordeaux', color: 'Brown', age: 3}, {ownerId:13, name: 'Rin Tin Tin', breed: 'German Shepherd', age: 5}, {ownerId:14, name: 'Benji', breed: 'unknown', age: 1}, {ownerId:15, name: 'Wishbone', breed: 'Jack Russell Terrier', color: 'White', age: 2}, {ownerId:16, name: 'Marley', breed: 'Labrador Retriever', color: 'Yellow', age: 9}, {ownerId:17, name: 'Beethoven', breed: 'St. Bernard', age: 3}, {ownerId:18, name: 'Lassie', breed: 'Collie', color: 'tan and white', age: 4}, {ownerId:19, name: 'Snoopy', breed: 'beagle', color: 'black and white', age: 6}, {ownerId:20, name: 'Max', breed: 'Westie', age: 7, origin: 'Scotland'}, {ownerId:20, name: 'Gigi', breed: 'Spaniel', color: 'Chocolate', age: 1, origin: 'Great Britain'}, {ownerId:20, name: 'Mimo', breed: 'Boxer', color: 'Chocolate', age: 2, origin: 'Germany'}, {ownerId:20, name: 'Bepo', breed: 'French Bulldog', color: 'Grey', age: 4, origin: 'France'}, ]); }); after(function (done) { var Dog = dynamoose.model('Dog'); Dog.$__.table.delete(function (err) { if(err) { done(err); } delete dynamoose.models.Dog; done(); }); }); it('Basic Query', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('ownerId').eq(2).exec(function (err, dogs) { should.not.exist(err); dogs.length.should.eql(2); done(); }); }); it('Basic Query One', function (done) { var Dog = dynamoose.model('Dog'); Dog.queryOne('ownerId').eq(1).exec(function (err, oneDog) { should.not.exist(err); should.exist(oneDog); oneDog.ownerId.should.eql(1); done(); }); }); it('Basic Query on Secondary Global Index', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('Jack Russell Terrier').exec(function (err, dogs) { should.not.exist(err); dogs.length.should.eql(4); dogs[0].ownerId.should.eql(1); done(); }); }); it('Query on Secondary Global Index with range - no results', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('Jack Russell Terrier').where('ownerId').eq(4).exec(function (err, dogs) { should.not.exist(err); dogs.length.should.eql(0); done(); }); }); it('Query on Secondary Global Index with range', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('unknown').where('ownerId').lt(8).exec(function (err, dogs) { should.not.exist(err); dogs.length.should.eql(2); done(); }); }); it('Query on Secondary Global Index with same hashKey', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('ownerId').eq(20).where('color').beginsWith('Choc').exec(function (err, dogs) { should.not.exist(err); dogs.length.should.eql(2); dogs[0].name.should.eql('Gigi'); dogs[1].name.should.eql('Mimo'); done(); }); }); it('Query on Secondary Global Index with same hashKey and 2nd in index list', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('ownerId').using('BreedRangeIndex').eq(20).where('breed').beginsWith('Sp').exec(function (err, dogs) { should.not.exist(err); dogs.length.should.eql(1); dogs[0].name.should.eql('Gigi'); done(); }); }); it('Query with Secondary Local Index as range', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('ownerId').eq(20).where('origin').beginsWith('G').exec(function (err, dogs) { should.not.exist(err); dogs.length.should.eql(2); done(); }); }); it('where() must follow eq()', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').where("test") .exec(function (err) { should.exist(err.message); err.message.should.eql('Invalid Query state: where() must follow eq()'); done(); }); }); it('filter() must follow comparison', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').filter("test") .exec(function (err) { should.exist(err.message); err.message.should.eql('Invalid Query state: filter() must follow comparison'); done(); }); }); it('eq must follow query()', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').lt(5) .exec(function (err) { should.exist(err.message); err.message.should.eql('Invalid Query state: eq must follow query()'); done(); }); }); it('Should throw first error', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').lt(5) .where().filter().compVal().beginsWith().in().between() .exec(function (err) { should.exist(err.message); err.message.should.eql('Invalid Query state: eq must follow query()'); done(); }); }); it('Basic Query on SGI descending', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('Jack Russell Terrier').descending().exec(function (err, dogs) { should.not.exist(err); dogs.length.should.eql(4); dogs[0].ownerId.should.eql(15); done(); }); }); it('Basic Query on SGI ascending', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('Jack Russell Terrier').ascending().exec(function (err, dogs) { should.not.exist(err); dogs.length.should.eql(4); dogs[0].ownerId.should.eql(1); done(); }); }); it('Basic Query on SGI limit 1', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('Jack Russell Terrier').limit(1).exec(function (err, dogs) { should.not.exist(err); should.exist(dogs.lastKey); dogs.length.should.eql(1); dogs[0].ownerId.should.eql(1); done(); }); }); it('Basic Query on SGI startAt key', function (done) { var Dog = dynamoose.model('Dog'); var startKey = { breed: { S: 'Jack Russell Terrier' }, ownerId: { N: '1' }, name: { S: 'Foxy Lady' } }; Dog.query('breed').eq('Jack Russell Terrier').startAt(startKey).limit(1).exec(function (err, dogs) { should.not.exist(err); should.exist(dogs.lastKey); dogs.length.should.eql(1); dogs[0].ownerId.should.eql(2); done(); }); }); it('Basic Query on SGI with attributes', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('Jack Russell Terrier').attributes(['name']).exec(function (err, dogs) { should.not.exist(err); should.not.exist(dogs.lastKey); dogs.length.should.eql(4); dogs[0].should.not.have.property('ownerId'); dogs[0].should.have.property('name', 'Foxy Lady'); done(); }); }); it('Basic Query with consistent read', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('ownerId').eq(2).consistent().exec(function (err, dogs) { should.not.exist(err); dogs.length.should.eql(2); done(); }); }); it('Basic Query on SGI with filter contains', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('Jack Russell Terrier') .where('ownerId').eq(1) .filter('color').contains('Black').exec() .then(function (dogs) { dogs.length.should.eql(1); dogs[0].ownerId.should.eql(1); done(); }) .catch(done); }); it('Basic Query on SGI with filter contains on list', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('Jack Russell Terrier') .where('ownerId').eq(2) .filter('siblings').contains('Quincy').exec() .then(function (dogs) { // console.log('The dogs', dogs); dogs.length.should.eql(1); dogs[0].ownerId.should.eql(2); done(); }) .catch(done); }); it('Basic Query on SGI with filter null', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('unknown') .filter('color').not().null().exec() .then(function (dogs) { dogs.length.should.eql(5); done(); }) .catch(done); }); it('Basic Query on SGI with filter not null', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('unknown') .filter('color').null().exec() .then(function (dogs) { dogs.length.should.eql(0); done(); }) .catch(done); }); it('Basic Query on SGI with filter le', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('unknown') .where('ownerId').le(11) .exec() .then(function (dogs) { dogs.length.should.eql(4); dogs[dogs.length - 1].ownerId.should.eql(11); done(); }) .catch(done); }); it('Basic Query on SGI with filter not le', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('unknown') .where('ownerId').not().le(11) .exec() .then(function (dogs) { dogs.length.should.eql(1); dogs[0].ownerId.should.eql(14); done(); }) .catch(done); }); it('Basic Query on SGI with filter ge', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('unknown') .where('ownerId').ge(11) .exec() .then(function (dogs) { dogs.length.should.eql(2); dogs[0].ownerId.should.eql(11); done(); }) .catch(done); }); it('Basic Query on SGI with filter not ge', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('unknown') .where('ownerId').not().ge(11) .exec() .then(function (dogs) { dogs.length.should.eql(3); dogs[0].ownerId.should.eql(5); done(); }) .catch(done); }); it('Basic Query on SGI with filter gt', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('unknown') .where('ownerId').gt(11) .exec() .then(function (dogs) { dogs.length.should.eql(1); dogs[0].ownerId.should.eql(14); done(); }) .catch(done); }); it('Basic Query on SGI with filter not gt', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('unknown') .where('ownerId').not().gt(11) .exec() .then(function (dogs) { dogs.length.should.eql(4); dogs[0].ownerId.should.eql(5); done(); }) .catch(done); }); it('Basic Query on SGI with filter not eq and not lt', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('unknown') .where('ownerId').not().lt(10) .and() .filter('color').not().eq('Brown') .exec() .then(function (dogs) { dogs.length.should.eql(1); dogs[0].ownerId.should.eql(11); done(); }) .catch(done); }); it('Basic Query on SGI with filter not contains or beginsWith', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('Jack Russell Terrier') .filter('color').not().contains('Brown') .or() .filter('name').beginsWith('Q').exec() .then(function (dogs) { dogs.length.should.eql(2); done(); }) .catch(done); }); it('beginsWith() cannot follow not()', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('Jack Russell Terrier') .filter('color').not().contains('Brown') .or() .filter('name').not().beginsWith('Q') .exec(function (err) { should.exist(err.message); err.message.should.eql('Invalid Query state: beginsWith() cannot follow not()'); done(); }); }); it('Basic Query on SGI with filter between', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('Jack Russell Terrier') .filter('age').between(5,7) .exec(function (err, dogs) { should.not.exist(err); dogs.length.should.eql(1); dogs[0].ownerId.should.eql(2); done(); }); }); it('between() cannot follow not()', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('Jack Russell Terrier') .filter('age').not().between(5,7) .exec(function (err) { should.exist(err.message); err.message.should.eql('Invalid Query state: between() cannot follow not()'); done(); }); }); it('Basic Query on SGI with filter in', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('Jack Russell Terrier') .filter('color').in(["White and Brown", "White"]) .exec(function (err, dogs) { should.not.exist(err); dogs.length.should.eql(3); dogs[0].ownerId.should.eql(2); done(); }); }); it('in() cannot follow not()', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('Jack Russell Terrier') .filter('color').not().in(["White and Brown", "White"]) .exec(function (err) { should.exist(err.message); err.message.should.eql('Invalid Query state: in() cannot follow not()'); done(); }); }); it('Query.count', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('ownerId').eq(20).count().all().exec() .then(function (count) { count.should.eql(4); done(); }) .catch(done); }); it('Query.counts', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('breed').eq('unknown') .and() .filter('color').not().eq('Brown') .counts().all().exec() .then(function (counts) { counts.scannedCount.should.eql(5); counts.count.should.eql(4); done(); }) .catch(done); }); it('Query.all', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('ownerId').eq(20).limit(2).all().exec() .then(function (dogs) { dogs.length.should.eql(4); done(); }) .catch(done); }); it('Query.all(1, 3)', function (done) { var Dog = dynamoose.model('Dog'); Dog.query('ownerId').eq(20).limit(1).all(1000, 3).exec() .then(function (dogs) { dogs.length.should.eql(3); dogs.timesQueried.should.eql(3); done(); }) .catch(done); }); it('Should allow multiple indexes and query correctly', function (done) { var schema = new dynamoose.Schema({ id: { type: String, hashKey: true, required: true }, orgId: { type: String, index: [{ global : true, name : 'OrganizationCreateAtIndex', rangeKey : 'createdAt', throughput: 1 }, { global : true, name : 'OrganizationExpectedArriveAtIndex', rangeKey : 'expectedArriveAt', throughput: 1 }], required: true, }, expectedArriveAt: Date },{ throughput: 1, timestamps: true }); var Log = dynamoose.model('Log-1', schema); var log1 = new Log({id: "test1", orgId: "org1", expectedArriveAt: Date.now()}); log1.save(function() { Log.query('orgId').eq("org1") .where('expectedArriveAt').lt( new Date() ) .exec() .then(function(res){ res.length.should.eql(1); Log.query('orgId').eq("org1") .where('createdAt').lt( new Date() ) .exec() .then(function(res){ res.length.should.eql(1); done(); }) .catch(function(e){ done(e); }); }) .catch(function(e){ done(e); }); }); }); it('Should allow multiple local indexes and query correctly', async function () { var schema = new dynamoose.Schema({ id: { type: String, hashKey: true, }, orgId: { type: String, rangeKey: true, }, updatedAt: { type: Date, index: { global: false, name : 'OrganizationUpdatedAtIndex' } }, expectedArriveAt: { type: Date, index: { global: false, name : 'OrganizationExpectedArriveAtIndex' } } },{ throughput: 1, timestamps: true }); var Log = dynamoose.model('Log-2', schema); var log1 = new Log({id: "test1", orgId: "org1", expectedArriveAt: Date.now()}); var log2 = new Log({id: "test1", orgId: "org2", expectedArriveAt: Date.now()}); await log1.save(); await log2.save(); var res = await Log.query('id').eq("test1") .where('expectedArriveAt').lt( new Date() ) .exec() res.length.should.eql(2); var res2 = await Log.query('id').eq("test1") .where('updatedAt').le( log1.createdAt.getTime() ) .exec(); res2.length.should.eql(1); }); });