API

AWS Credentials

There are three ways to specify AWS credentials:

  • .aws/credentials
  • Environment Variables
  • AWS.config

Dynamoose Object

var dynamoose = require('dynamoose');

dynamoose.model(name, schema, [options])

Compiles a new model or looks up an existing one. options is optional.

Default options:

{
  create: true, // Create table in DB, if it does not exist,
  update: false, // Update remote indexes if they do not match local index structure
  waitForActive: true, // Wait for table to be created before trying to use it
  waitForActiveTimeout: 180000 // wait 3 minutes for table to activate
}

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.setDefaults(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 // Create table in DB if it does not exist
}

It is recommended that create be disabled for production environments.

dynamoose.setDefaults( { create: false });

dynamoose.Schema

The dynamoose Schema class, used to create new schema definitions. For example:

var appleSchema = new dynamoose.Schema({
  id: Number, 
  type: String
});

dynamoose.Table

Table class

Schema

Schemas are used to define DynamoDB table attributes and their constraints.

Creating a new Schema

Schemas are created using new Schema(attrDefObj, options).

The first argument (attrDefObj) is an object containing attribute definitions. Keys of this object correspond to attributes in the resulting DynamoDB table. The values of these keys define constraints on those attributes (as well as a few handy features…). See Attribute Definitions for a more thorough description.

The second argument (options) defines options for the table that are beyond the scope of individual attributes. See Schema Options for more.

The following is an example of creating a new Schema:

var Schema = dynamoose.Schema;

var dogSchema = new Schema({
  ownerId: {
    type: Number,
    validate: function(v) { return v > 0; },
    hashKey: true
  },
  name: {
    type: String,
    rangeKey: true,
    index: true // name: nameLocalIndex, ProjectionType: ALL
  },
  breed: {
    type: String,
    trim: true,
    required: true,
    index: {
      global: true,
      rangeKey: 'ownerId',
      name: 'BreedIndex',
      project: true, // ProjectionType: ALL
      throughput: 5 // read and write are both 5
    }
  },
  color: {
    lowercase: true,
    type: [String],
    default: ['Brown']
  },
  age: Number
},
{
  throughput: {read: 15, write: 5}
});

Attribute Types

Attribute Types define the domain of a particular attribute. For example, a name might be set to String or age to Number.

The following table describes valid Attribute Types, and their translation to DynamoDB types:

Attribute Type Resulting DynamoDB Type
String ‘S’
Number ‘N’
Boolean* ‘S’ or ‘BOOL’
Date ‘N’
Object* ‘S’ or ‘M’
Array* ‘S’ or ‘L’
Buffer ‘B’
[String] ‘SS’
[Number] ‘NS’
[Boolean] ‘SS’
[Date] ‘NS’
[Object] ‘SS’
[Array] ‘SS’

* Use useNativeBooleans and useDocumentTypes to change DynamoDB type

Attribute Definitions

Attribute definitions define constraints on a particular attribute specified in a Schema. Attribute definitions may be an object type (see Attribute Types) or an object with the following options:

type: AttributeType required

Required for all attribute definitions. Defines the attribute type. See Attribute Types.

hashKey: boolean

Sets the attribute as the table’s hash key. If this option isn’t specified in a schema, then the first attribute is defined as the hash key.

rangeKey: boolean

Sets the attribute as the table’s range key.

required: boolean

Sets the attribute as a ‘required’ attribute. Required attributes must not be saved as undefined or null, or an error will be thrown.

index: boolean | object | [objects]

Defines the attribute as a local or global secondary index. Index can either be true, an index definition object or and array of index definition objects. The array is used define multiple indexes for a single attribute. 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 with the current model instance, and the response is assigned to the attribute’s value.

If it is a value, the value is simply assigned.

function(model) {
    return model.name +'_'+ model.category;
}

forceDefault: boolean

(default: false) Will force the default value to always be applied to the attribute event if it already set. This is good for populating data that will be used as sort or secondary indexes.

validate: function, regular expression, or 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, model) {
  if(valid)
    return true;
  else
    return false;
}

If it is a RegExp, it is compared using RegExp.test(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 returned from the DB.

toDynamo: function

Adds a setter function that will directly set the value to the DB. This skips all type management and parsing normally provided by options.set.

fromDynamo: function

Adds a getter function that will be used to transform the value directly returned from the DB. This skips all type management and parsing normally provided by options.get.

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: number | {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 (for example: {read: 5, write: 2}). If it is a number, both read and write are configured to that number. If it is omitted, the read and write values will be set to 1.

var schema = new Schema({...}, {
  throughput: 5
});
var schema = new Schema({...}, {
  throughput: {
    read: 5,
    write: 2
  }
});

useNativeBooleans: boolean

Store Boolean values as Boolean (‘BOOL’) in DynamoDB. Default to false (i.e store as JSON string).

var schema = new Schema({...}, {
  useNativeBooleans: true
});

useDocumentTypes: boolean

Store Objects and Arrays as Maps (‘M’) and Lists (‘L’) types in DynamoDB. Defaults to false (i.e. store as JSON string)

var schema = new Schema({...}, {
  useDocumentTypes: true
});

timestamps: boolean | {createdAt: string, updatedAt: string}

Defines that schema must contain fields to control creation and last update timestamps. If it is set to true, this fields will be createdAt for creation date and updatedAt for last update. for example:

var schema = new Schema({...}, {
  throughput: 5,
  timestamps: true
});

You can specify the names that the fields will use, like in the following example:

var schema = new Schema({...}, {
  throughput: 5,
  timestamps: {
    createdAt: 'creationDate',
    updatedAt: 'lastUpdateDate'
  }
});

expires: number | {ttl: number, attribute: string}

Defines that schema must contain and expires attribute. This field is configured in DynamoDB as the TTL attribute. If set to a number, an attribute named “expires” will be added to the schema. The default value of the attribute will be the current time plus the expires value. The expires value is in seconds.

The attribute will be a standard javascript Date in the object, and will be stored as number (‘N’) in the DyanmoDB table. The stored number is in seconds. More information about DynamoDB TTL

var schema = new Schema({...}, {
  expires: 7*24*60*60 // 1 week in seconds
});

You can specify the attribute name by passing an object:

var schema = new Schema({...}, {
  expires: {
    ttl: 7*24*60*60, // 1 week in seconds
    attribute: 'ttl' // ttl will be used as the attribute name
  }
});

saveUnknown: boolean

Specifies that attributes not defined in the schema will be saved and retrieved. This defaults to false.

var schema = new Schema({...}, {
  saveUnknown: true
});

attributeToDynamo: function

A function that accepts name, json, model, defaultFormatter.

This will override attribute formatting for all attributes. Whatever is returned by the function will be sent directly to the DB.

var schema = new Schema({...}, {
  attributeToDynamo: function(name, json, model, defaultFormatter) {
    switch(name) {
        case 'specialAttribute':
            return specialFormatter(json);
        default:
            return specialFormatter(json);
    }
  }
});

attributeFromDynamo: function

A function that accepts name, json, fallback.

This will override attribute parsing for all attributes. Whatever is returned by the function will be passed directly to the model instance.

var schema = new Schema({...}, {
  attributeFromDynamo: function(name, json, defaultParser) {
    switch(name) {
        case 'specialAttribute':
            return specialParser(json);
        default:
            return defaultParser(json);
    }
  }
});

Methods

You can add custom methods to your Schema

Static Methods

Can be accessed from the compiled Schema, similar to how scan() and query() are called. this will refer to the compiled schema within the definition of the function.


// Construction:
var ModelSchema = new Schema({...})

ModelSchema.statics.getAll = function(cb){
  this.scan().exec(cb)
}

var Model = dynamoose.model('Model', ModelSchema)

// Using:
Model.getAll(function(err, models)=>{
    models.forEach(function(model){
      console.log(model)
    })
})

Instance Methods

Can be accessed from a newly created model. this will refer to the instace of the model within the definition of the function.


// Construction:
var ModelSchema = new Schema({
  name:String
})

ModelSchema.methods.setName = function(name) {
  this.name = name
}

var Model = dynamoose.model('Model', ModelSchema)

// Using:
var batman = new Model({name: "Bruce"})
batman.setName("Bob")

Model

Create Model From Schema

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. Will overwrite the item.

odie.save(function (err) {
  if(err) { return console.log(err); }
  console.log('Ta-da!');
});

odie.save({
    condition: '#o = :ownerId',
    conditionNames: { o: 'ownerId' },
    conditionValues: { ownerId: 4 }
  }, function (err) {
  if(err) { return console.log(err); }
  console.log('Ta-da!');
});

Model.batchPut(items, options, callback)

Puts multiple items in the table. Will overwrite existing items.

Dog.batchPut([
  {
    ownerId: 2,
    name: 'Princes',
    breed: 'Jack Russell Terrier',
    color: ['White', 'Brown'],
    cartoon: true
  },
  {
    ownerId: 3,
    name: 'Toto',
    breed: 'Terrier',
    color: ['Brown'],
    cartoon: false
  },
  {
    ownerId: 4,
    name: 'Odie',
    breed: 'Beagle',
    color: ['Tan'],
    cartoon: true
  },
  {
    ownerId: 5,
    name: 'Lassie',
    breed: 'Beagle',
    color: ['Tan'],
    cartoon: false
  }], function (err, dogs) {
    if (err) { return console.log(err); }
    console.log('Ta-da!');
  });

Options

overwrite: boolean

Overwrite existing item. Defaults to true.

condition: string

An expression for a conditional update. See the AWS documentation for more information about condition expressions.

conditionNames: object

A map of name substitutions for the condition expression.

conditionValues: object

A map of values for the condition expression. Note that in order for automatic object conversion to work, the keys in this object must match schema attribute names.

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.populate(options)

Populates paths from an item from the table.

(Only promise mode yet)

Dog = dynamoose.model('Dog', {
    id: {
      type:  Number
    },
    name: {
      type: String
    },
    parent: Number
  })

/*
Available dogs
{ id: 1, name: 'Odie'}
{ id: 2, name: 'Rex', parent: 1 }
{ id: 3, name: 'Fox', parent: 2 }
*/

Dog.get(3)
  .then(function(dog) {
    return dog.populate({
      path: 'parent',
      model: 'Dog',
      populate: {
        path: 'parent',
        model: 'Dog'
      }
    });
  })
  .then(function(dog) {
    console.log(dog);
    /*
    {
      id: 3,
      name: 'Fox',
      parent: {
        id: 2,
        name: 'Rex',
        parent: {
          id: 1,
          name: 'Odie'
        }
      }
    }
    */
  });

Populate with range and hash key

If the object to populate has both a range and hash key, you must store both in the attribute.

const CatWithOwner = dynamoose.model('CatWithOwner',
  {
    id: {
      type:  Number
    },
    name: {
      type: String
    },
    owner: {
      name: String,
      address: String
    }
  }
);

const Owner = dynamoose.model('Owner',
  {
    name: {
      type: String,
      hashKey: true
    },
    address: {
      type: String,
      rangeKey: true
    },
    phoneNumber: String
  }
);

var owner = new Owner({
  name: 'Owner',
  address: '123 A Street',
  phoneNumber: '2345551212'
});

var kittenWithOwner = new CatWithOwner({
  id: 100,
  name: 'Owned',
  owner: {
    name: owner.name,
    address: owner.address
  }
});

CatWithOwner.get(100)
.then(function(cat) {
  should.not.exist(cat.owner.phoneNumber);
  return cat.populate({
    path: 'owner',
    model: 'Owner'
  });
})
.then(function(catWithOwnerPopulated) {
  ...
});

Model.batchGet(keys, options, callback)

Gets multiple items from the table.

Dog.batchGet([{ownerId: 4, name: 'Odie'}, {ownerId: 5, name: 'Lassie'}], function (err, dogs) {
  if (err) { return console.log(err); }
  console.log('Retrieved two dogs: ' + dogs);
});

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.batchDelete(keys, options, callback)

Deletes multiple items from the table.

Dog.batchDelete([
  { ownerId: 2, name: 'Princes' },
  { ownerId: 3, name: 'Toto' },
  { ownerId: 4, name: 'Odie' },
  { ownerId: 5, name: 'Lassie'}
], function (err) {
  if (err) { return console.log(err); }
  console.log('Bye bye my friends');
});

Model.update(key, update, options, callback)

Model.update(keyWithUpdate, callback)

Updates and existing item in the table. Three types of updates: $PUT, $ADD, and $DELETE.

The key can either be its own object or combined with the update object.

$PUT

Put is the default behavior. The three example below are identical.

key and updated are separate

Dog.update({ownerId: 4, name: 'Odie'}, {age: 1}, function (err) {
  if(err) { return console.log(err); }
  console.log('Just a puppy');
})

key and updated are combined

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

Adds one or more attributes to the item.

Dog.update({ownerId: 4, name: 'Odie'}, {$ADD: {age: 1}}, function (err) {
  if(err) { return console.log(err); }
  console.log('Birthday boy');
})

$DELETE

Removes one or more attributes from an item.

Dog.update({ownerId: 4, name: 'Odie'}, {$DELETE: {age: null}}, function (err) {
  if(err) { return console.log(err); }
  console.log('Too old to keep count');
})

Options

allowEmptyArray: boolean

If true, the attribute can be updated to an empty array. If false, empty arrays will remove the attribute. Defaults to false.

createRequired: boolean

If true, required attributes will be filled with their default values on update (regardless of you specifying them for the update). Defaults to false.

updateTimestamps: boolean

If true, the timestamps attributes will be updated. Will not do anything if timestamps attribute were not specified. Defaults to true.

condition: string

An expression for a conditional update. See the AWS documentation for more information about condition expressions.

conditionNames: object

A map of name substitutions for the condition expression.

conditionValues: object

A map of values for the condition expression. Note that in order for automatic object conversion to work, the keys in this object must match schema attribute names.

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.

Note: You must provide an eq for the hash key.

Dog.query('breed').eq('Beagle').exec(function (err, dogs) {
  // Look at all the beagles
});
Dog.query({breed: {eq: 'Beagle'} }, function (err, dogs) {
  // Look at all the beagles
});

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 attribute on which to filter.

query.and()

Use add logic for filters.

query.or()

Use or logic for filters.

query.not()

Inverts the filter logic that follows.

query.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 greater than or equal a. and less than or equal to b.

query.contains(value)

Filter contains the value.

query.beginsWith(value)

Filter begins with the value.

query.in(values)

Filter is in values array.

query.limit(limit)

The maximum number of items to evaluate (not necessarily the number of matching items). If DynamoDB processes the number of items up to the limit while processing the results, it stops the operation and returns the matching values up to that point, and a key in lastKey to apply in a subsequent operation, so that you can pick up where you left off. Also, if the processed data set size exceeds 1 MB before DynamoDB reaches this limit, it stops the operation and returns the matching values up to the limit, and a key in lastKey to apply in a subsequent operation to continue the operation. For more information, see Query and Scan in the Amazon DynamoDB Developer Guide.

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 lastKey returned in query.exec() callback.

query.attributes(attributes)

Set the list of attributes to return.

query.count()

Return the number of matching items, rather than the matching items themselves.

query.counts()

Return the counts object of matching items, rather than the matching items themselves:

{
    "count": 2,
    "scannedCount": 1000
}

If you used a filter in the request, then count is the number of items returned after the filter was applied, and scannedCount is the number of matching items before the filter was applied.

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) {
  // Look at all the Terriers
});
Dog.scan({breed: {contains: 'Terrier'} }, function (err, dogs) {
  // Look at all the Terriers
});

To get all the items in a table, do not provide a filter.

Dog.scan().exec(function (err, dogs) {
  // Look at all the dogs
  if(dogs.lastKey) { // More dogs to get
    Dog.scan().startAt(dogs.lastKey).exec(function (err, dogs) {
      // Look more dogs
    });
  }
});

To use the raw AWS filter in scanning especially for nested fields scan purposes, compose the filter object and pass it in.

  • The TableName field in raw filter is not necessary to be specified. If it is left blank, the model name will be used as default table name.
var Dog = dynamoose.model('Dog');
// this should be composed, ref: http://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_Scan.html
var filter = {
  FilterExpression: 'details.timeWakeUp = :wakeUp',
  ExpressionAttributeValues: {
    ':wakeUp': '8am'
  }
};

Dog.scan(filter).exec()
  .then(function(dogs) {
    console.log(dogs);
  })
  .catch(function(err) {
    console.error(err);
  });

scan.exec(callback)

Executes a scan against a table

scan.all([delay[, max]])

Recursively scan as long as lastKey exists. This function will also return a property called timesScanned indicating how many scans were completed.

delay is the time (in seconds) between recursive scans. Default: 1sec

max is the maximum number of recursive scans. Default: 0 - unlimited

scan.parallel(totalSegments)

Preforms a parallel scan on the table.

totalSegments is the number of parallel scans

The results will be merged into a single array. .lastKey will be an array of lastKey objects.

Warning this can consume a lot of capacity.

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. If null, undefined, or a empty string is passed as the value, scan.null() is called.

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 value is greater than or equal a. and less than or equal to b.

scan.limit(limit)

The maximum number of items to evaluate (not necessarily the number of matching items). If DynamoDB processes the number of items up to the limit while processing the results, it stops the operation and returns the matching values up to that point, and a key in lastKey to apply in a subsequent operation, so that you can pick up where you left off. Also, if the processed data set size exceeds 1 MB before DynamoDB reaches this limit, it stops the operation and returns the matching values up to the limit, and a key in lastKey to apply in a subsequent operation to continue the operation. For more information, see Query and Scan in the Amazon DynamoDB Developer Guide.

scan.startAt(key)

Start scan at key. Use lastKey returned in scan.exec() callback.

scan.attributes(attributes)

Set the list of attributes to return.

scan.count()

Return the number of matching items, rather than the matching items themselves.

scan.counts()

Return the counts object of matching items, rather than the matching items themselves:

{
    "count": 2,
    "scannedCount": 1000
}

If you used a filter in the scan, then count is the number of items returned after the filter was applied, and scannedCount is the number of matching items before the filter was applied.

scan.consistent()

Scan with consistent read.