Quick Start

Getting Started

If you’re looking to get started right away with ElectroDB, checkout code examples in the /examples directory, or for guided examples in this document below. Additionally, the section Building Queries shows examples of every and has descriptions of all methods available in ElectroDB. If you use TypeScript, the section TypeScript contains useful exported types to use in your project.

ElectroDB Playground

ElectroDB Playground allows you to try ElectroDB in the browser — experiment with new concepts, experience ElectroDB’s game-changing type inference, and share your modeling with team members.

Try out and share ElectroDB Models, Services, and Single Table Design at www.electrodb.fun

Installation

ElectroDB exists as package available in NPM

NPM

# install as a dependency in your project
npm install electrodb --save

Yarn

# install as a dependency in your project
yarn add electrodb

Usage

TypeScript

import { Entity, Service } from "electrodb";

JavaScript

const { Entity, Service } = require("electrodb");

Basic Example

ElectroDB focuses on simplifying the process of modeling, enforcing data constraints, querying across entities, and formatting complex DocumentClient parameters.

In this section you will model a simple entity: a Book inside a used book store.

Install dependencies

NPM

# install as a dependency in your project
npm install electrodb aws-sdk --save

Yarn

# install as a dependency in your project
yarn add electrodb aws-sdk

Create your table

With Single-Table Design, generic key and indexes names are preferred. The following DynamoDB table definition creates a generic Pay-Per-Request table that contains a single Global Secondary Index.

The table definition below will define TableName, IndexName, and AttributeName values that will then map to your Model Definition. These values are highlighted for increased visibility and are highlighted on both the Table Definition and the Entity Schema

{
  // highlight-next-line
  "TableName": "electro",
  "KeySchema": [
    {
      // highlight-next-line
      "AttributeName": "pk",
      "KeyType": "HASH"
    },
    {
      // highlight-next-line
      "AttributeName": "sk",
      "KeyType": "RANGE"
    }
  ],
  "AttributeDefinitions": [
    {
      // highlight-next-line
      "AttributeName": "pk",
      "AttributeType": "S"
    },
    {
      // highlight-next-line
      "AttributeName": "sk",
      "AttributeType": "S"
    },
    {
      // highlight-next-line
      "AttributeName": "gsi1pk",
      "AttributeType": "S"
    },
    {
      // highlight-next-line
      "AttributeName": "gsi1sk",
      "AttributeType": "S"
    }
  ],
  "GlobalSecondaryIndexes": [
    {
      // highlight-next-line
      "IndexName": "gsi1pk-gsi1sk-index",
      "KeySchema": [
        {
          // highlight-next-line
          "AttributeName": "gsi1pk",
          "KeyType": "HASH"
        },
        {
          // highlight-next-line
          "AttributeName": "gsi1sk",
          "KeyType": "RANGE"
        }
      ],
      "Projection": {
        "ProjectionType": "ALL"
      }
    }
  ],
  "BillingMode": "PAY_PER_REQUEST"
}

Define your Entity

After creating the table defined above, we can begin modeling our Entity. Note and compare the highlighted lines as they are mappings to the table definition above.

import DynamoDB from "aws-sdk/clients/dynamodb";
import { Entity } from "electrodb";

const client = new DynamoDB.DocumentClient();

// highlight-next-line
const table = "electro";

const Book = new Entity(
  {
    model: {
      entity: "book",
      version: "1",
      service: "store",
    },
    attributes: {
      storeId: {
        type: "string",
      },
      bookId: {
        type: "string",
      },
      price: {
        type: "number",
        required: true,
      },
      title: {
        type: "string",
      },
      author: {
        type: "string",
      },
      condition: {
        type: ["EXCELLENT", "GOOD", "FAIR", "POOR"] as const,
        required: true,
      },
      genre: {
        type: "set",
        items: "string",
      },
      published: {
        type: "string",
      },
    },
    indexes: {
      byLocation: {
        pk: {
          // highlight-next-line
          field: "pk",
          composite: ["storeId"],
        },
        sk: {
          // highlight-next-line
          field: "sk",
          composite: ["bookId"],
        },
      },
      byAuthor: {
        // highlight-next-line
        index: "gsi1pk-gsi1sk-index",
        pk: {
          // highlight-next-line
          field: "gsi1pk",
          composite: ["author"],
        },
        sk: {
          // highlight-next-line
          field: "gsi1sk",
          composite: ["title"],
        },
      },
    },
    // add your DocumentClient and TableName as a second parameter
  },
  { client, table },
);

Create Book

await Book.create({
  bookId: "beedabe8-e34e-4d41-9272-0755be9a2a9f",
  storeId: "pdx-45",
  author: "Stephen King",
  title: "IT",
  condition: "GOOD",
  price: 15,
  genre: ["HORROR", "THRILLER"],
  published: "1986-09-15",
}).go();

Update Book

await Book.patch({
  bookId: "beedabe8-e34e-4d41-9272-0755be9a2a9f",
  storeId: "pdx-45",
})
  .set({
    price: 10,
    condition: "FAIR",
  })
  .go();

Get Book

const book = await Book.get({
  bookId: "beedabe8-e34e-4d41-9272-0755be9a2a9f",
  storeId: "pdx-45",
}).go();

Get Books by Author

const { data, cursor } = await Book.query
  .byAuthor({ author: "Stephen King" })
  .go();

Get (Cheap) Books by Store Location

const { data, cursor } = await Book.query
  .byLocation({ storeId: "pdx-45" })
  .where(({ price }, { lte }) => lte(price, 10))
  .go();