Skip to content
The promised DynamoDB client of your dreams
Branch: master
Clone or download
Pull request Compare This branch is 22 commits ahead of liyi1234:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
example
lib
test
.editorconfig
.gitignore
.jscsrc
.jshintrc
.npmignore
.travis.yml
README.md
package.json

README.md

Dynamise

Build Status Dependency Status devDependency Status

Dynamise wraps the native DynamoDB methods from aws-sdk for node.js in promisifed versions and also provides some sugar syntax to interact with your database.

Examples: Look into the example folder to learn about the available functions

API Docs

All the following examples assume that you got a client for a specific endpoint, like so:

var db = require("dynamise");
var client = db(endpoint);

Most of the methods, unless stated otherwise, return native ES6 Promises. See MDN for details.

  1. Table operations
  1. Item operations
  1. Others

client.endpoint()

Return the actual endpoint

var endpoint = client.endpoint();

/*
e.g.

{ protocol: 'http:',
  host: 'localhost:8000',
  port: 8000,
  hostname: 'localhost',
  pathname: '/',
  path: '/',
  href: 'http://localhost:8000/',
  title: 'local' }
*/

client.listTables(params)

You will get an array with all the table names associated with the endpoint.

client.listTables()
  .then(function (res) {
    console.log(res.TableNames); // ['TableOne', 'TableTwo', 'TableThree']
  });

See DynamoDB.listTables for more information.

client.create("tableName")

Adds a new table to the database. If you have set(tableDefintion) a table definition already, you can use the tableName as a String parameter. Otherwise you are able to hand over a complete table object.

Example

var tableDefinition = {
    // complete table definition
}

client.create(tableDefinition).then(doMore);

// or
client.set({tableName: tableDefinition});
client.create(tableName);

Note: create() waits for the table to be in an ACTIVE state.

See DynamoDB.createTable for more information.

client.read("tableName")

You will get certain information about the table specified.

client.read("TableOne")
  .then(function (res) {
    console.log(res);
  });

You response might look like this:

{ AttributeDefinitions:
   [ { AttributeName: 'id', AttributeType: 'S' }, ... ],
  TableName: 'TableOne',
  ProvisionedThroughput:
   { ... },
  KeySchema:
   [ { AttributeName: 'id', KeyType: 'HASH' } ],
  CreationDateTime: Wed Jun 10 2015 16:47:24 GMT+0200 (CEST),
  ItemCount: 0,
  TableSizeBytes: 0,
  TableStatus: 'ACTIVE' }

See DynamoDB.describeTable for more information.

Returns information about the table, including the current status of the table, when it was created, the primary key schema, and any indexes on the table.

client.remove("tableName")

Deletes the table and all of its items.

// Assume "TableOne" exists
client.remove("TableOne")
 .then(function (res) {
   // res contains a TableDescription object
   // res.TableStatus === 'DELETING'
 });

See DynamoDB.deleteTable for mor information.

client.status("tableName")

This function uses client.read(tableName) but only fetches the following information:

  • TableSizeBytes (total size in bytes)
  • TableStatus (CREATING, DELETING, UPDATING, ACTIVE)
  • ItemCount (number of items)

and if the table is upgradable (true|false).

client.status("TableOne")
  .then(function (res) {
    // do something with res
  })
  .catch(function (err) {
    // throws a ResourceNotFoundException if table does not exist
  });

A response object might look like this:

{ TableSizeBytes: 0,
  TableStatus: 'ACTIVE',
  ItemCount: 0,
  Upgradable: false }

client.active("tableName")

Checks if the table state is ACTIVE and returns an object with table data. If the table is not active it waits for the table to become active.

client.active("TableOne")
  .then(function (res) {
    if (res.TableName === "TableOne") {
      console.log("You got the right table!");
    }
  });

Your response object might look like this:

{ AttributeDefinitions:
   [ { AttributeName: 'id', AttributeType: 'S' },
  TableName: 'Example',
  ProvisionedThroughput:
   { ... },
  KeySchema:
   [ { AttributeName: 'id', KeyType: 'HASH' } ],
  CreationDateTime: Thu Jun 11 2015 15:31:42 GMT+0200 (CEST),
  ItemCount: 0,
  TableSizeBytes: 0,
  TableStatus: 'ACTIVE' }

Uses client.read(tableName) and therefore DynamoDB.describeTable.

client.update(params)

Update the Provisioned Throughput for the given table. You are also able to add and/or update global secondary indexes.

See DynamoDB.updateTable

##client.recreate("tableName")

Recreates the table if exists or creates the table if not and waits until active.

client.multiUpsert(tables)

Does an multiUpsert on the tables specified in the tables object. The param tables should look like

var tables = {
  "TableA": [item1, item2, ...],
  "TableB": [item1, item2, ...]
}

See DynamoDB.batchWriteItem for more information.

client.multiRead(params)

Returns an object with a TableName attribute containing an array with all read items.

var params = {
  RequestItems: {
    Example:{ // TableName
      Keys:[
        {id:"1", email:"m@epha.ch"},
        {id:"1", FileId:"d@epha.ch"},
        // ...
      ]
    }
  }
};

client.multiRead(params)
  .then(function (resItems) {
    // do something
  };

See DynamoDB.batchGetItem for more information.

client.table("tableName").read(hash,range)

client.table("Example").read("1", "m@epha.com")
  .then(function (resItem) {
    if(!resItem) {
      // there is no such item
    }
    // do something with the item
  };

Returns an item with the given hash and range (primary key). If there exists no such item in the database, nothing will be returned.

See DynamoDB.getItem.

client.table("tableName").patch(item)

With patch() you can do the following operations on your item:

  • Add new attributes
  • Delete attributes
  • Update attributes
// the following item does already exist in the database
var item = {
  id: "1", // hash
  email: "m@epha.com",
  name: "markus",
  points: "3",
  role: "user"
}

client.table("Example").patch({
  id: "1",  // hash and/or range keys cannot be updated
  points: null, // will be removed
  role: "admin", // will be updated
  rule: "user-management" // will be added
});

See DynamoDB.updateItem for more information.

client.table("tableName").upsert(item)

var item = {id: "1", email: "m@epha.com"};

client.table("Example").upsert(item);

Creates a new item. If the item already exists, it will be fully replaced.

See DynamoDB.putItem for more information.

client.table("tableName").multiUpsert(items)

Uses the batchWriteItem method from AWS.DynamoDB to do an upsert on many items. Note that batchWriteItem cannot update items. Items which already exist are fully replaced.

var items = [
  { UserId: "1", FileId: "file#1" },
  { UserId: "2", FileId" "file#2" },
  ...
]

client.table("Example").multiUpsert(items).then(...);

NOTE: If you want to multiUpsert on different tables use the client.multiUpsert() method. Actually, this method is using it either.

See DynamoDB.batchWriteItem for more information.

client.table("tableName").upload(items)

Upload an array of items using multiUpsert. Returns a Promise which handles the events internally.

var items = [
  { UserId: "1", FileId: "file#1" },
  { UserId: "2", FileId" "file#2" },
  ...
];

client.table("Example").upload(items).then(...);

NOTE: Currently this is only an alias for client.table("tableName").multiUpsert()

client.table("tableName").createUploadStream()

Returns an instance of UploadStream to handle an upload via stream manually.

There are mainly two possible scenarios to use the UploadStream

  1. download one whole table from a database and upload it to another database
  2. upload data from a JSON file

Use DownloadStream to upload data to another database using UploadStream

var downloadStream = client.table("TableOne").createDownloadStream();
var uploadStream = client.table("TableTwo").createUploadStream();

downloadStream.pipe(uploadStream);

uploadStream.on("finish", function () {
  console.log("finished uploading items");
});

uploadStream.on("error", function (err) {
  console.trace(err);
});

Upoad data from a JSON file using UploadStream

In this case you will need JSONStream to pipe data accordingly to UploadStream.

var fs = require("fs");
var path = require("path");
var jsonStream = require("JSONStream").parse("*");
var uploadStream = client.table("Example").createUploadStream();

// Read data from a file using fs.createReadStream()
var jsonFileStream = fs.createReadStream(path.resolve(__dirname, "data.json"));

// And now pipe anything to uploadStream
jsonFileStream.pipe(jsonStream).pipe(uploadStream);

uploadStream.on("finish", function () {
  console.log("finished uploading items");
});

uploadStream.on("error", function (err) {
  console.error(err);
});

client.table("tableName").download()

Actually this is an alias for client.table(tableName).scanAll() - does a complete scan.

client.table("tableName").createDownloadStream()

Returns an instance of DownloadStream to handle a download manually.

var download = client.table("TableOne").createDownloadStream();
var downloadedItems = [];

download.on("data", function (chunk) {
  downloadedItems.push(chunk);
});

download.on("end", function () {
  console.log("finished downloading " + downloadedItems.length + " items");
});

download.on("error", console.error);

client.table("tableName").remove(hash,range)

Deletes a single item in a table.

See DynamoDB.deleteItem for more information.

client.table("tableName").find(params)

Used to find items based on conditions.

client.table("Example")
      .find(params) // params is optional
      .where("UserId").equals("1") // hash key
      .and("FileId").equals("2");
      .run()

You are able to pass a params Object to find() with attributes defined in DynamoDB.query. We build some sugar functions to make this even easier.

IMPORTANT NOTICE: If you pass KeyConditions make sure you are using the correct signature related to dynamodb-doc Condition Object. You have to hand over an array containing condition objects as described in the link above.

- index()

The same as params would include { IndexName: "IndexNameValue" }.

client.table("Example")
    .find()
    .index("indexName")}
    (...)
    .run();

- all()

DynamoDB has several limitations related to how big a query response can be (more information about limitations can be found here). Thus we provide a all() method which handles the pagination for you.

Otherwise you would have to evaluate responses LastEvaluatedKey attribute youself.

client.table("Example")
    .find()
    .all()
    (...)
    .run();

- where()

This is used to define a hash key where a certain equals() condition is applied to.

client.table("Example")
  .find()
  .where("id").equals("1")
  .run();

Note: On hash keys you are only allowed to perform an equals() condition.

- and()

This is used to define a range key where a certain condition is applied to.

client.table("Example")
  .find()
  .where("id").equals("1")
  .and("email").equals("t@epha.com")
  .run();

You are also allowed to apply the following conditions:

  • lt() - lower than
  • le() - lower than or equal
  • gt() - greater than
  • ge() - greater than or equal
  • between()
  • beginsWith()

client.table("tableName").query(params)

var params = {
	TableName: "TableOne",
	KeyConditions: [
		client.Condition("id", "EQ", "1")
	]
}

client.table("TableOne").query(params)
	.then(function (res) {
	  // do something with your query
	});

Your response is an array with all items which fit your query conditions.

To know more about a params object, please look at DynamoDB.query.

client.table("tableName").scan(params)

Returns items of a table.

If the total number of scanned items exceeds the maximum data set size limit of 1 MB, the scan stops and results are returned to the user as a LastEvaluatedKey value to continue the scan in a subsequent operation.

client.table("TableOne").scan()
  .then(function (res) {
    // do something with the items
  });

Your response object might look like this:

{ Count: 8467,
  ScannedCount: 8467,
  Items: [ ... ], // array with 8467 items
  // LastEvaluatedKey:
}

This method is helpful in case of pagination. Look at the following example:

var limit = 10;
client.table(tableName).scan({Limit: limit})
  .then(function (res) {
    // process res.Items
    console.log(res.Items);

    // are there still more items to fetch?
    if (res.LastEvaluatedKey) {
      console.log("There are still more items to fetch...");

      // build a new query with LastEvaluatedKey
      params = {
        Limit: 10,
        ExclusiveStartKey: res.LastEvalutedKey
      }

      // Now use this params object to query the next 10 items with scan(params)
    }
  })
  .catch(console.error);

Note: This is a very basic and simple example. You would write methods like next() to fetch the next x items and use it in a loop or wait for a user to query the next items. There is a more complex example in the example/ directory.

See DynamoDB.scan for more information.

client.table("tableName").scanAll(params)

Uses client.table("tableName").scan() to scan all items of a table. You will get an array with all items of a table.

client.table("TableOne").download()
  .then(function (res) {
    console.log(res.length) // number of items
  });

Error Reporting

A small note on error reporting: Please make sure to always use a .catch() block when working with the API, otherwise you might miss some errors.

client.table("TableOne").scanAll()
  .then()
  .catch(function (err) {
    // log error, for example
    // console.trace(err.stack)
  });

DynamoDB methods

Additionally we expose the underlying promisified methods to access the native DynamoDB methods.

return client.dynamo.getItem(params);
// return client.dynamo.batchWriteItem(params);

Sponsors

You can’t perform that action at this time.