API
AWS Credentials
There are three ways to specify AWS credentials:
- .aws/credentials
- Environment Variables
- AWS.config
Dynamoose Object
const 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
streamOptions: { // sets table stream options
enabled: false, // sets if stream is enabled on the table
type: undefined // sets the stream type (NEW_IMAGE | OLD_IMAGE | NEW_AND_OLD_IMAGES | KEYS_ONLY) (https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_StreamSpecification.html#DDB-Type-StreamSpecification-StreamViewType)
},
serverSideEncryption: false, // Set SSESpecification.Enabled (server-side encryption) to true or false (default: false)
defaultReturnValues: 'ALL_NEW' // sets ReturnValues for the UpdateItem operation (NONE | ALL_OLD | UPDATED_OLD | ALL_NEW | UPDATED_NEW) (https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_UpdateItem.html)
}
Basic example:
const Cat = dynamoose.model('Cat', {
id: Number,
name: String
});
streamOptions: object (optional)
Indicates whether stream is enabled or disabled on the table and dictates which type of stream the table should have. This is passed into into the StreamSpecification
option property when creating the table.
serverSideEncryption: boolean
Indicates whether server-side encryption is enabled (true) or disabled (false) on the table. This boolean will be passed into the SSESpecification.Enabled
option property when creating the table. Currently (when feature was implemented) DynamoDB doesn’t support updating a table to add or remove server-side encryption, therefore this option will only be respected on creation of table, if table already exists in DynamoDB when using Dynamoose this value will be ignored.
const model = dynamoose.model('Cat', {...}, {
streamOptions: {
enabled: true,
type: "NEW_AND_OLD_IMAGES"
},
serverSideEncryption: true
});
dynamoose.local(url)
Configure Dynamoose to use a DynamoDB local for testing. url
defaults to ‘http://localhost:8000’.
dynamoose.local();
dynamoose.local('http://localhost:1234');
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.setDDB
Function to set the DynamoDB object that Dynamoose uses.
const AWS = require('aws-sdk');
const dynamoDB = new AWS.dynamoDB();
dynamoose.setDDB(dynamoDB);
dynamoose.revertDDB
Function to revert the DynamoDB object that Dynamoose uses to the default.
dynamoose.revertDDB();
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
prefix: '', // Default prefix for all DynamoDB tables
suffix: '' // Default suffix for all DynamoDB tables
}
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:
const appleSchema = new dynamoose.Schema({
id: Number,
type: String
});
dynamoose.Table
Table class
AWS X-Ray Support
You can achieve Amazon Web Services X-Ray support using a configuration similar to the following.
const AWSXRay = require('aws-xray-sdk');
const dynamoose = require('dynamoose');
dynamoose.AWS = AWSXRay.captureAWS(require('aws-sdk'));
dynamoose.setDocumentClient(documentClient)
Sets the document client for DynamoDB. This can be used to integrate with Amazon Web Services DAX.
dynamoose.transaction(items[, options][, cb])
Allows you to run DynamoDB transactions. Accepts an array as the items
parameter. You can pass in a RAW DynamoDB transaction object, or use the Dynamoose Model.transaction
helper methods.
dynamoose.transaction([
User.transaction.update({id: "user1"}, {$ADD: {balance: -100}}),
Charge.transaction.create({userid: "user1", product: "product1", amount: 100, status: "successful"}),
Product.transaction.update({id: "product1"}, {$ADD: {inventory: -1}}),
Credit.transaction.delete({id: "credit1"}),
{
Delete: {
Key: {
id: {
S: 'helloworld'
}
},
TableName: 'MyOtherTable'
}
}
]).then(function (result) {
console.log(result);
}).catch(function (err) {
console.error(err);
});
If you use a custom RAW DynamoDB transaction object, you must have created a corresponding model in Dynamoose.
options
properties:
type
(string): The type of transaction Dynamoose will run. Can either be “get”, or “write”. By default if all of your items are of type “get”, it will default to “get”, otherwise, will default to “write”.
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
},
race: {
type: String,
enum: ['Golden retriever', 'Beagle']
},
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 istrue
. - 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;
}
Your function may also be an async function with await statements in it, or return a promise. For example:
function(model) {
return new Promise(resolve => {
setTimeout(function() {
resolve("My default value");
}, 1000);
});
}
enum: Array of strings
Force value to be one of the enumeration values.
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, object, 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;
}
You can also pass in a function that returns a promise, or an async function:
async function(v) {
const result = await networkRequest(v);
if (result.value === "true") {
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 ===
.
If an object is passed in it must have a validator property that is a function. You can set the isAsync
property to true, to enable callback functionality. If you are using promises, isAsync
is not required. For example:
{
isAsync: true, // default: false
validator: function(v, model, cb) {
setTimeout(function() {
var phoneRegex = /\d{3}-\d{3}-\d{4}/;
var msg = v + ' is not a valid phone number!';
// First argument is a boolean, whether validator succeeded
// 2nd argument is an optional error message override
cb(phoneRegex.test(v), msg);
}, 5);
},
disableModelParameter: false // default: false, if enabled will only pass in value and callback, and not the model
}
Running any Dynamoose method that calls the validate
method indirectly from within the validate
method will cause an infinate loop.
The property name validate
is also an alias for validator
. The property name validator
will take priority if both are passed in.
set: function | object |
Adds a setter function that will be used to transform the value before writing to the DB. You can pass in a standard function that returns the new result, an async function that uses await syntax in it, or a function that returns a promise.
You can also pass in an object that defines extra settings and allows for callback based async set. For example:
{
isAsync: true, // default: false
set: function(v, cb) {
setTimeout(function() {
cb("My item: " + v, msg);
}, 5);
}
}
get: function | object |
Adds a getter function that will be used to transform the value returned from the DB, fired only if there is a value returned from the DB. You can pass in a standard function that returns the new result, an async function that uses await syntax in it, or a function that returns a promise.
You can also pass in an object that defines extra settings and allows for callback based async get. For example:
{
isAsync: true, // default: false
get: function(v, cb) {
setTimeout(function() {
cb("My item: " + v, msg);
}, 5);
}
}
toDynamo: function | object |
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
.
Your function may also be an async function with await statements in it, or return a promise. For example:
function(val) {
return new Promise(resolve => {
setTimeout(function() {
resolve({S: "My custom value"});
}, 1000);
});
}
If an object is passed in it must have a toDynamo property that is a function. You can set the isAsync
property to true, to enable callback functionality. If you are using promises, isAsync
is not required. For example:
{
isAsync: true, // default: false
toDynamo: function(v, cb) {
setTimeout(function() {
cb({S: "My custom value"});
}, 5);
}
}
fromDynamo: function | object |
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
.
Your function may also be an async function with await statements in it, or return a promise. For example:
function(val) {
return new Promise(resolve => {
setTimeout(function() {
resolve("My custom value");
}, 1000);
});
}
If an object is passed in it must have a fromDynamo property that is a function. You can set the isAsync
property to true, to enable callback functionality. If you are using promises, isAsync
is not required. For example:
{
isAsync: true, // default: false
fromDynamo: function(v, cb) {
setTimeout(function() {
cb({S: "My custom value"});
}, 5);
}
}
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 | string | {read: number, write: number} |
Sets the throughput of the DynamoDB table on creation. 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. Throughput will only be respected on table creation, and will not update the throughput of an existing table.
If this property is set to "ON_DEMAND"
the table will be created using PAY_PER_REQUEST BillingMode.
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 true
(i.e store as DynamoDB boolean).
var schema = new Schema({...}, {
useNativeBooleans: true
});
useDocumentTypes: boolean
Store Objects and Arrays as Maps (‘M’) and Lists (‘L’) types in DynamoDB. Defaults to true
(i.e. store as DynamoDB maps and lists).
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, returnExpiredItems: boolean, defaultExpires: function}
Defines that schema must contain an 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, unless an optional defaultExpires property is passed in. 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
returnExpiredItems: true, // if expired items will be returned or not (default: true)
defaultExpires: function () { // optional, will default to `ttl` if not defined, this function is mainly used to allow the expires to be set to null or undefined, without resetting to the normal default
return null;
}
}
});
saveUnknown: boolean or array
Specifies that attributes not defined in the schema will be saved and retrieved. This defaults to false.
var schema = new Schema({...}, {
saveUnknown: true
});
If an array is passed in, only attributes that are in the array passed in will be saved and retrieved.
var schema = new Schema({...}, {
saveUnknown: ['name', 'age'] // only `name` and `age` unknown attributes will be saved and retrieved from DynamoDB
});
errorUnknown: boolean
Specifies that any attributes not defined in the schema will throw an error if encountered while parsing records from DynamoDB. This defaults to false.
var schema = new Schema({...}, {
errorUnknown: true
});
attributeToDynamo: function
A function that accepts name, json, model, defaultFormatter, options
.
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, options) {
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. Model methods can be accessed via this.model(modelName)
.
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
},
friends: {
type: [String],
default: [],
}
});
dogSchema.method('becomeFriends', function (otherDog) {
this.friends = this.friends || [];
otherDog.friends = otherDog.friends || [];
this.friends.push(otherDog.name);
otherDog.friends.push(this.name);
this.model('Dog').batchPut([this, otherDog]);
});
var Dog = dynamoose.model('Dog', dogSchema);
var dog1 = new Dog({ownerId: 137, name: 'Snuffles'});
var dog2 = new Dog({ownerId: 138, name: 'Bill'});
dog1.becomeFriends(dog2);
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 = async function (cb) {
let results = await this.scan().exec();
while (results.lastKey) {
results = await this.scan().startKey(results.startKey).exec();
}
return results;
}
const Model = dynamoose.model('Model', ModelSchema)
// Using:
Model.getAll((err, models) => {
models.forEach((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:
const ModelSchema = new Schema({
name: String
});
ModelSchema.methods.setName = function (name) {
this.name = name
};
const Model = dynamoose.model('Model', ModelSchema);
// Using:
const batman = new Model({name: "Bruce"});
batman.setName("Bob");
Model
Create Model From Schema
const Dog = dynamoose.model('Dog', dogSchema);
new Model(object)
Creates a new instance of the model. Object keys are assigned to the new model.
const 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!');
});
Options:
- overwrite: should overwrite the existing item in DynamoDB (default: true)
- updateExpires: should update the expires timestamp if exists (default: false)
- updateTimestamps: should update the updatedAt timestamp if exists (default: true)
- returnRequest: should not make request to DynamoDB and resolve with request (default: false)
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.
updateExpires: boolean
Update the expires
timestamp if exists. Defaults to false.
updateTimestamps: boolean
Should update the updatedAt
timestamp if exists. Defaults to false.
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);
});
You can set options.returnRequest
to true, to resolve the get request instead of making the request.
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);
});
You can set options.returnRequest
to true, to resolve the get request instead of making the request.
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'
}
}
}
*/
});
Dog.scan().exec()
.then(function(dogs) {
return Promise.all(dogs.map(function(dog) {
return dog.populate({
path: 'parent',
model: 'Dog'
});
}));
})
.then(function(dogs) {
console.log(dogs);
});
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');
});
options
parameters:
update
(boolean): Will return the object deleted (default: false), if set to false and no object was deleted this function will fail silently.returnRequest
(boolean): Will resolve with the request object instead of making the request (default: false)
model.delete([options, ]callback)
Deletes the item from the table. The options
parameter is optional, and should be a object type if passed in. The callback
parameter is the function that will be called once the item has been deleted from the table. The error
and item
(if update
is set to true) will be passed in as parameters to the callback function. The options object accepts the same parameters as described above in Model.delete
.
odie.delete(function(err) {
if (err) {
return console.log(err);
}
console.log('Bye bye Odie');
});
model.originalItem()
This function returns the last item that was saved/received from DynamoDB. This can be useful to view the changes made since the last DynamoDB save/received that your application made for a given document. This function will return a JSON object that represents the original item.
odie.originalItem(); // {ownerId: 4, name: '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 an 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. These attributes must be of the number or set type. If the attribute already exists it will be manipulated instead. If it’s a number the provided value will be added mathematically to the existing value. If the attribute is a set the provided value is appended to the set.
Dog.update({ownerId: 4, name: 'Odie'}, {$ADD: {age: 1}}, function (err) {
if (err) {
return console.log(err);
}
console.log('Birthday boy is one year older');
})
$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.
updateExpires: boolean
If true, the expires
attributes will be updated. Will not do anything if expires attribute were not specified. Defaults to false.
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.
returnValues: string
From the AWS documentation Use ReturnValues if you want to get the item attributes as they appear before or after they are updated. For UpdateItem, the valid values are:
- NONE - If ReturnValues is not specified, or if its value is NONE, then nothing is returned. (This setting is DynamoDB’s default.)
- ALL_OLD - Returns all of the attributes of the item, as they appeared before the UpdateItem operation.
- UPDATED_OLD - Returns only the updated attributes, as they appeared before the UpdateItem operation.
- ALL_NEW - Returns all of the attributes of the item, as they appear after the UpdateItem operation. (This setting is the Dynamoose default.)
- UPDATED_NEW - Returns only the updated attributes, as they appear after the UpdateItem operation.
Model.transaction
This object has the following methods that you can call.
Model.transaction.get
Model.transaction.create
Model.transaction.delete
Model.transaction.update
Model.transaction.conditionCheck
You can pass in the same parameters into each method that you do for the normal (non-transaction) methods.
These methods are only meant to only be called to instantiate the dynamoose.transaction
array.
Model.transaction.conditionCheck(key, options)
This method allows you to run a conditionCheck when running a DynamoDB transaction.
Example:
Model.transaction.conditionCheck("credit1", {
condition: "amount > :request",
conditionNames: {
request: "request"
},
conditionValues: {
request: 100
}
})
Options
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.getTableReq()
The function will return the object used to create the table with AWS. You can use this to create the table manually, for things like the Serverless deployment toolkit, or just to peak behind the scenes and see what Dynamoose is doing to create the table.
Dog.getTableReq();
// {
// AttributeDefinitions: attrDefs,
// TableName: name,
// KeySchema: keySchema,
// ProvisionedThroughput: provThroughput
// }
Model.plugin(pluginPackage[, pluginOptions])
WARNING: PLUGINS IS CURRENTLY IN BETA. THIS FUNCTIONALITY MIGHT CHANGE AT ANYTIME WITHOUT WARNING. DO NOT CONSIDER THIS FEATURE TO BE STABLE.
This is how you can add plugins to be run on your model. For example you can use this function like so.
const MyPlugin = require('ThePluginPackage');
const MyPluginB = require('ThePluginPackageB');
const Model = dynamoose.model('Puppy', {
id: {
type: Number,
validate: function(v) {
return v > 0;
}
},
name: String,
owner: String,
age: {
type: Number
}
});
Model.plugin(MyPlugin); // this plugin will always take priority over the plugin below and be run first
Model.plugin(MyPluginB, {username: 'test', password: 'test'}); // this plugin will always take priority second and will be run after the first plugin, this plugin also passes options into the plugin
module.exports = Model;
Query
Model.query(query, options, callback)
Queries a table or index. The query parameter can either be 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
});
Model.queryOne(query, options, callback)
Queries a table or index, sets query.limit
to 1
.
query.exec(callback)
Executes the query against the table or index.
query.all([delay[, max]])
Recursively query as long as lastKey exists. This function will also return a property called timesQueried
indicating how many queries were completed.
delay
is the time (in miliseconds) between recursive queries. Default: 1000ms (1sec)
max
is the maximum number of recursive queries. Default: 0 - unlimited
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.
query.using(index)
You can manually specify which index to use by adding the query.using
method to your query chain. The string you pass into the query.using
method must match the name of an index on your table. This method is not required, by default Dynamoose will try to figure out which index to use based on your schema.
Dog.query('ownerId').using('BreedRangeIndex').eq(20).where('breed').beginsWith('Sp')
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 miliseconds) between recursive scans. Default: 1000ms (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.
Plugins (BETA)
WARNING: PLUGINS IS CURRENTLY IN BETA. THIS FUNCTIONALITY MIGHT CHANGE AT ANYTIME WITHOUT WARNING. DO NOT CONSIDER THIS FEATURE TO BE STABLE.
Please view the Model.plugin
documentation for how to use plugins in your own models. This documentation will be going over how to create plugins from scratch.
Overview
All plugins will export a function. Dynamoose will pass in 2 parameters into that function. plugin
and options
. options
is the object that was passed into Model.plugin
. plugin
properties are defined below.
plugin.setName
Set the name of the plugin.
Parameters accepted
name
- Name of plugin (string)
plugin.setDescription
Set the description of the plugin.
Parameters accepted
description
- Description of plugin (string)
plugin.on
Adds a listener to emitted events from Dynamoose. You can return a promise in the callback
method that you pass in, and when it is called, Dynamoose will await
for your promise to complete before continuing. Your promise must resolve
and not reject
. You can resolve an object with the property resolve
or reject
to return or reject with that result to the end user. At that point Dynamoose will take no further action. This can be useful if you want to handle more of the interaction with the user.
Parameters accepted
- [
event
] - Type of event you wish to listen for from Dynamoose, you can view possible options below, if not passed in it will catch all events (string) (optional) - [
stage
] - Type of stage you wish you listen for from Dynamoose within the event, if not passed in it will catch all events (string) (optional) (note: if this is passed inevent
is required) callback
- Function to be run when event is emitted from Dynamoose (function)obj
- Object with properties and methods about event emitted from Dynamoose, you can view more details below (object)
Example Plugin Implementation
module.exports = (plugin, options) => {
plugin.setName('My Plugin'); // required
plugin.setDescription(''); // optional
plugin.on('init', () => { // this will handle all stages related to init
console.log('Plugin registered');
});
plugin.on('scan', 'preRequest', (obj) => { // this will handle only preRequest stages on the scan type
console.log('About to make request to DynamoDB');
});
plugin.on('scan', 'postRequest', (obj) => { // this will handle only postRequest stages on the scan type, and will wait for promise to resolve before moving on
return new Promise((resolve) => {
resolve({
resolve: 'Hello World' // 'Hello World' will be passed back to the promise/callback of the Dynamoose scan call
});
});
});
plugin.on('query', 'postRequest', (obj) => { // this will handle only postRequest stages on the scan type, and will wait for promise to resolve before moving on
return new Promise((resolve) => {
resolve({
reject: 'My Error' // 'My Error' will be passed back to the promise/callback of the Dynamoose scan call as an error (not successful)
});
});
});
return plugin;
}
Items Passed Into .on callback object
Below is the default object passed into the callback object, each event might add more properties and methods to this object.
{
model: _____, // the model instance (object)
modelName: _____, // the model name (string)
plugins: _____, // array of plugins registered to model (array)
plugin: _____, // the plugin that is being called (object)
event: {
type: _____, // the type of event that was emitted from Dynamoose (ex. "plugin:register") (string)
stage: _____ // the stage that was emitted from Dynamoose (ex. "pre", "post") (string)
}
actions: {
registerPlugin: _____ // register function to model, just a pointer to Model.plugin function (this can be useful for creating sub-plugins) (function)
}
}
Events emitted from Dynamoose
*
Catch all to run listener on all events emitted from Dynamoose.
plugin
Dynamoose will emit this event when your plugin is registered to a model.
Stages
init
- Dynamoose will emit this stage when your plugin has been registered to a model
Additional Items Added to Object
{
}
plugin:register
Dynamoose will emit this event when a new plugin is registered to a model.
Stages
pre
- Dynamoose will emit this stage when a new plugin is about to be registered to a modelpost
- Dynamoose will emit this stage when a new plugin has been registered to a model (remember: if you are listening for this stage within your plugin, this will be called after your plugin is registered, so almost instantly after it gets registered to a model)
Additional Items Added to Object
{
event: {
plugin: _____, // plugin package that is going to/has been registered (function)
pluginOptions: _____ // options that were passed into plugin registration (object)
}
}
model:scan
Dynamoose will emit this event when a scan is called on a model.
Stages
scan:called
- Dynamoose will emit this stage when a scan is about to startexec:start
- Dynamoose will emit this stage when an exec is calledrequest:pre
- Dynamoose will emit this stage when an scan request is about to be made to DynamoDBrequest:post
- Dynamoose will emit this stage when an scan request response has been received from DynamoDB
Additional Items Added to Object
{
event: {
scan: _____, // scan instance (object, Scan instance)
callback: _____ // the function that was passed into the scan exec function (function) (only valid on `exec:start`)
scanReq: _____ // the scan request object that will be sent to DynamoDB (object) (only valid on `request:pre`)
data: _____ // the scan data object that was received from DynamoDB (object) (only valid on `request:post`)
error: _____ // the scan error object that was received from DynamoDB (object) (only valid on `request:post`)
}
action: {
updateCallback: _____ // function to update callback that is called (fn: function) (only valid on `exec:start`)
updateScanReq: _____ // function to update scan request object that is sent to DynamoDB (reqObj: object) (only valid on `request:pre`)
updateData: _____ // function to update data that was received from DynamoDB scan before proceeding (dataObj: object) (only valid on `request:post`)
updateError: _____ // function to update error that was received from DynamoDB scan before proceeding (errorObj: object) (only valid on `request:post`)
}
}
model:get
Dynamoose will emit this event when a get is called on a model.
Stages
get:called
- Dynamoose will emit this stage when a get is about to startrequest:pre
- Dynamoose will emit this stage when a get request is about to be made to DynamoDBrequest:post
- Dynamoose will emit this stage when a get request response has been recieved from DynamoDB
Additional Items Added to Object
{
event: {
callback: _____ // the callback function for the get command (function)
key: _____ // the key for the get request (object)
options: _____ // the options passed into the get call (object)
getRequest: _____ // the options passed into the get request to DynamoDB (object) (only valid on `request:pre`)
error: _____ // the options passed into the get call (object) (only valid on `request:post`)
data: _____ // the options passed into the get call (object) (only valid on `request:post`)
}
action: {
updateCallback: _____ // function to update callback that is called (fn: function)
updateKey: _____ // function to update key that is sent to DynamoDB (key: string)
updateOptions: _____ // function to update options for the get call (options: object)
updateGetRequest: _____ // function to update request options for the get call (options: object) (only valid on `request:pre`)
updateError: _____ // function to update error received from DynamoDB (options: object) (only valid on `request:post`)
updateData: _____ // function to update data received from DynamoDB (options: object) (only valid on `request:post`)
}
}
model:query
Dynamoose will emit this event when a query is called on a model.
Stages
query:called
- Dynamoose will emit this stage when a query is about to startexec:start
- Dynamoose will emit this stage when an exec is calledrequest:pre
- Dynamoose will emit this stage when a query request is about to be made to DynamoDBrequest:post
- Dynamoose will emit this stage when a query request response has been received from DynamoDB
Additional Items Added to Object
{
event: {
query: _____, // query instance (object, Query instance)
callback: _____ // the function that was passed into the query exec function (function) (only valid on `exec:start`)
queryReq: _____ // the query request object that will be sent to DynamoDB (object) (only valid on `request:pre`)
data: _____ // the query data object that was received from DynamoDB (object) (only valid on `request:post`)
error: _____ // the query error object that was received from DynamoDB (object) (only valid on `request:post`)
}
action: {
updateCallback: _____ // function to update callback that is called (fn: function) (only valid on `exec:start`)
updateQueryReq: _____ // function to update query request object that is sent to DynamoDB (reqObj: object) (only valid on `request:pre`)
updateData: _____ // function to update data that was received from DynamoDB query before proceeding (dataObj: object) (only valid on `request:post`)
updateError: _____ // function to update error that was received from DynamoDB query before proceeding (errorObj: object) (only valid on `request:post`)
}
}
model:put
Dynamoose will emit this event when a put is called on a model.
Stages
put:called
- Dynamoose will emit this stage when a put is about to startrequest:pre
- Dynamoose will emit this stage when a put request is about to be made to DynamoDBrequest:post
- Dynamoose will emit this stage when a put request response has been received from DynamoDB
Additional Items Added to Object
{
event: {
options: _____, // options passed to put (object) (warning: in some cases this can be the callback function in the `put:called` stage)
callback: _____, // callback passed to put (function) (warning: in some cases this can be the null if options is not passed in) (only valid on `put:called`)
item: _____ // item that will be/has been saved to DynamoDB (function) (only valid on `request:*`)
error: _____ // the error object that was received from DynamoDB (object) (only valid on `request:post`)
}
action: {
updateCallback: _____ // function to update callback that is called (fn: function) (only valid on `put:called`)
updateOptions: _____ // function to update options object (reqObj: object) (only valid on `put:called`)
updateItem: _____ // function to update data that will be sent to DynamoDB (dataObj: object) (only valid on `request:pre`)
updateError: _____ // function to update error that was received from DynamoDB query before proceeding (errorObj: object) (only valid on `request:post`)
}
}