Dynamoose
Dynamoose is a modeling tool for Amazon's DynamoDB (inspired by Mongoose)
In switching from MongoDB/Mongoose to DynamoDB, we missed the modeling provided by Mongoose. There are several great modules out there, but they didn't match our needs. We created Dynamoose based on our usage.
Dynamoose uses the official AWS SDK.
Getting Started
Installation
$ npm install dynamoose
Example
Set AWS configurations in enviroment varable:
export AWS_ACCESS_KEY_ID="Your AWS Access Key ID"
export AWS_SECRET_ACCESS_KEY="Your AWS Secret Access Key"
export AWS_REGION="us-east-1"
Here's a simple example:
var dynamoose = require('dynamoose');
var Cat = dynamoose.model('Cat', { id: Number, name: String });
var garfield = new Cat({id: 666, name: 'Garfield'});
garfield.save();
Cat.get(666)
.then(function (badCat) {
console.log('Never trust a smiling cat. - ' + badCat.name);
});
API
Dynamoose
var dynamoose = require('dynamoose');
dynamoose.model(name, schema, [options])
Compiles a new model or looks up an existing model. options
is optional.
Default options
:
{
create: true,
waitForActive: true,
waitForActiveTimeout: 180000
}
Basic example:
var Cat = dynamoose.model('Cat', { id: Number, name: String });
dynamoose.local(url)
Configure dynamoose to use a DynamoDB local for testing.
url
defaults to 'http://localhost:8000'
dynamoose.local();
dynamoose.ddb()
Configures and returns the AWS.DynamoDB object
dynamoose.AWS
AWS object for dynamoose. Used to configure AWS for dynamoose.
dynamoose.AWS.config.update({
accessKeyId: 'AKID',
secretAccessKey: 'SECRET',
region: 'us-east-1'
});
dynamoose.defaults(options)
Sets the default to be used when creating a model. Can be modified on a per model by passing options to .model()
.
Default options
:
{
create: true
}
It is recommended that create
be disabled for production environments.
dynamoose.defaults( { create: false });
dynamoose.Schema
Schema class
dynamoose.Table
Table class
Schema
var Schema = dynamoose.Schema;
new Schema(schema, options)
Create a new Schema objects. The schema maps back to a DynamoDB table.
var dogSchema = new Schema({
ownerId: {
type: Number,
validate: function(v) { return v > 0; },
hashKey: true
},
name: {
type: String,
rangeKey: true,
index: true
},
breed: {
type: String,
trim: true,
required: true,
index: {
global: true,
rangeKey: 'ownerId',
name: 'BreedIndex',
project: true,
throughput: 5
}
},
color: {
lowercase: true,
type: [String],
default: ['Brown']
},
age: Number
},
{
throughput: {read: 15, write: 5}
});
Attribute Types
Each key represents an attribute in the DynamoDB table. The value of the key can either be the attribute type or an Object describing the attribute.
Valid attribute types are:
- String
- Number
- Boolean
- Date
- Object
- Array
- Buffer
String, Boolean, Object, and Array all map to the DynamoDB type of 'S'. Number and Date map to 'N'. Buffer maps to 'B'.
Types can also be sets of the above types. This is done by making the type an array. For example, [String] would be a String Set (DynamoDB 'SS') and [Number] would be a Number Set (DynamoDB 'NS').
Attribute Definition
type: AttributeType required
Required for all attribute definitions. Defines the attribute type. See Attribute Types.
hashKey: boolean
Defines the hash key attribute for the table. If no attribute is defined as the hash key, the first attribute is assumed to be the hash key.
rangeKey: boolean
Defines the range key attribute.
required: boolean
Defines if the attribute is required. Prior to saving an entry, if the attribute is undefined or null, an error will be thrown.
index: boolean | {...}
Defines the attribute as a local or global secondary index. Index can either be true or an index definition object. The index definition object can contain the following keys:
- name: 'string' - Name of index (Default is `attribute.name + (global ? 'GlobalIndex' : 'LocalIndex')``).
- global: boolean - Set the index to be a global secondary index. Attribute will be the hash key for the Index.
- rangeKey: 'string' - The range key for a global secondary index.
- project: boolean | ['string', ...] - Sets the attributes to be projected for the index.
true
projects all attributes, false
projects only the key attributes, and ['string', ...] projects the attributes listed. Default is true
. - throughput: number | {read: number, write: number} - Sets the throughput for the global secondary index.
default: function | value
Applies a default to the attribute's value when saving, if the values is null or undefined.
If default is a function, the function is called, and the response is assigned to the attribute's value.
If it is a value, the value is simply assigned.
validate: function | RegExp | value
Validation required before for saving.
If validate is a function, the function is used to validate the attribute's value. The function must have the signature:
function(value) {
if(valid)
return true;
else
return false;
}
If it is a RegExp, it is compared using RegExp.text(value)
.
If it is a value, it is compared with ===
.
set: function
Adds a setter function that will be used to transform the value before writing to the DB.
get: function
Adds a getter function that will be used to transform the value return from the DB.
trim: boolean
Trim whitespace from string when saving to DB.
lowercase: boolean
Convert to lowercase when saving to DB.
uppercase: boolean
Convert to uppercase when saving to DB.
Options
throughput: boolean | {read: number, write: number}
Sets the throughput of the DynamoDB table. The value can either be a number or an Object with the keys read and write {read: 5, write: 2}
. If it is a number, both read and write are configured to the same number. If it is omitted, the default value is 1 for both read and write.
var schema = New Schema({...}, { throughput: 5});
var schema = New Schema({...}, { throughput: { read: 5, write: 2 } });
Model
var Dog = dynamoose.model('Dog', dogSchema);
new Model(object)
Creates a new instance of the model. Object keys are assigned to the new model.
var odie = new Dog({
ownerId: 4,
name: 'Odie',
breed: 'Beagle',
color: ['Tan'],
cartoon: true
});
model.put(options, callback) & model.save(options, callback)
Puts the item in the DynamoDB table.
odie.save(function (err) {
if(err) { return console.log(err); }
console.log('Ta-da!');
});
Model.create(object, options, callback)
Creates a new instance of the model and save the item in the table.
Dog.create({
ownerId: 4,
name: 'Odie',
breed: 'Beagle',
color: ['Tan'],
cartoon: true
}, function(err, odie) {
if(err) { return console.log(err); }
console.log('Odie is a ' + odie.breed);
});
Model.get(key, options, callback)
Gets an item from the table.
Dog.get({ownerId: 4, name: 'Odie'}, function(err, odie) {
if(err) { return console.log(err); }
console.log('Odie is a ' + odie.breed);
});
Model.delete(key, options, callback)
Deletes an item from the table.
Dog.delete({ownerId: 4, name: 'Odie'}, function(err) {
if(err) { return console.log(err); }
console.log('Bye bye Odie');
});
model.delete(callback)
Deletes the item from the table.
odie.delete(function(err) {
if(err) { return console.log(err); }
console.log('Bye bye Odie');
});
Model.query(query, options, callback)
Queries a table or index. If callback is not provided, then a Query object is returned. See Query.
Model.queryOne(query, options, callback)
Same functionality as query except only return the first result object (if any). See Query.
Model.scan(filter, options, callback)
Scans a table. If callback is not provided, then a Scan object is returned. See Scan.
Model.update(key, update, callback)
Updates and existing item in the table. Three types of updates: $PUT, $ADD, and $DELETE. Refer to DynamoDB's updateItem documentation for details on how PUT, ADD, and DELETE work.
$PUT
Put is the default behavior. The two example below are identical.
Dog.update({ownerId: 4, name: 'Odie'}, {age: 1}, function (err) {
if(err) { return console.log(err); }
console.log('Just a puppy');
})
Dog.update({ownerId: 4, name: 'Odie'}, {$PUT: {age: 1}}, function (err) {
if(err) { return console.log(err); }
console.log('Just a puppy');
})
$ADD
Dog.update({ownerId: 4, name: 'Odie'}, {$ADD: {age: 1}}, function (err) {
if(err) { return console.log(err); }
console.log('Birthday boy');
})
$DELETE
Dog.update({ownerId: 4, name: 'Odie'}, {$DELETE: {age: null}}, function (err) {
if(err) { return console.log(err); }
console.log('Too old to keep count');
})
Query
Model.query(query, options, callback)
Queries a table or index. The query parameter can either the the hash key of the table or global index or a complete query object. If the callback is provided, the exec command is called automatically, and the query parameter must be a query object.
Dog.query('breed').eq('Beagle').exec(function (err, dogs) {
});
Dog.query({breed: {eq: 'Beagle'} }, function (err, dogs) {
});
query.exec(callback)
Executes the query against the table or index.
query.where(rangeKey)
Set the range key of the table or index to query.
query.filter(filter)
Set the atribulte on which to filter.
query.and()
Use add logic for filters.
query.or()
Use or logic for filters.
scan.not()
Inverts the filter logic that follows.
scan.null()
Filter attribute for null.
query.eq(value)
Hash, range key, or filter must equal the value provided. This is the only comparison option allowed for a hash key.
query.lt(value)
Range key or filter less than the value.
query.le(value)
Range key or filter less than or equal value.
query.ge(value)
Range key or filter greater than or equal value.
query.gt(value)
Range key or filter greater than the value.
query.beginsWith(value)
Range key or filter begins with value
query.between(a, b)
Range key or filter is between values a and b.
Attribute is greater than the value.
scan.contains(value)
Filter contains the value.
scan.beginsWith(value)
Filter begins with the value.
scan.in(values)
Filter is in values array.
query.limit(limit)
Limit the number of responses.
query.consistent()
Query with consistent read.
query.descending()
Sort in descending order.
query.ascending()
Sort in ascending order (default).
query.startAt(key)
Start query at key. Use LastEvaluatedKey returned in query.exec() callback.
query.attributes(attributes)
Set the attributes to return.
Scan
Model.scan(filter, options, callback)
Scans a table. The optional filter parameter can either be an attribute of the table or a complete filter object. If the callback is provided, the exec command is called automatically, and the scan parameter must be a Scan object.
Dog.scan('breed').contains('Terrier').exec(function (err, dogs) {
});
Dog.scan({breed: {contains: 'Terrier'} }, function (err, dogs) {
});
To get all the items in a table, do not provide a filter.
Dog.scan().exec(function (err, dogs, lastKey) {
if(lastKey) {
Dog.scan().startAt(lastKey).exec(function (err, dogs, lastKey) {
});
}
});
scan.exec(callback)
Executes a scan against a table
scan.and()
For readability only. Scans us AND logic for multiple attributes. and()
does not provide any functionality and can be omitted.
scan.where(filter) | scan.filter(filter)
Add additional attribute to the filter list.
scan.not()
Inverts the filter logic that follows.
scan.null()
Scan attribute for null.
scan.eq(value)
Attribute is equal to the value.
scan.lt(value)
Attribute is less than the value.
scan.le(value)
Attribute is less than or equal value.
scan.ge(value)
Attribute is greater than or equal value.
scan.gt(value)
Attribute is greater than the value.
scan.contains(value)
Attribute contains the value.
scan.beginsWith(value)
Attribute begins with the value.
scan.in(values)
Attribute is in values array.
scan.between(a, b)
Attribute is between value a and b.
scan.limit(limit)
Limit scan response to limit.
scan.startAt(key)
Start scan at key. Use LastEvaluatedKey returned in scan.exec() callback.
scan.attributes(attributes)
Set the attributes to return.