Permalink
Branch: master
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
365 lines (258 sloc) 8.93 KB

Overview

Begin Data is an easy to use, fast, durable, highly scalable, and fully managed key-value and document database that comes bundled with every Begin app.

Begin Data is easy to learn and implement, and is designed to accommodate most general persistence use cases.

Here's a simple example of a Function using Begin Data:

let data = require('@begin/data')
let begin = require('@architect/functions') // Reads & writes session data

exports.handler = async function http(request) {
  let session = await begin.http.session.read(request)
  let account = await data.get({
    table: 'accounts',
    key: session.accountID
  })
  return {
    type: 'text/html; charset=utf8',
    body: `Hello ${account.name}!`
  }
}

Tables & keys

Begin Data documents have two mandatory properties:

  • table - String (required)
    • Property by which documents are grouped
    • Values may be 1-50 of the following characters: [a-zA-Z0-9.,:-/+?&=@]
  • key - String
    • Property by which documents are indexed
    • Values may be 1-50 of the following characters: [a-zA-Z0-9.,:-/+?&=@]
    • If not supplied, Begin Data will automatically supply a pseudo-random, unique, immutable key

Optionally, documents may possess ttl property.

Here's a Function performing a quick document read using table and key:

// src/html/get-*/index.js
let data = require('@begin/data')

exports.handler = async function route(req) {

  let table = 'greetings'
  let key = 'Japanese'
  let hello = await data.get({table, key})

  return {
    type: 'text/html; charset=utf8',
    body: `"Hello" in ${key} is: ${hello}!`
  }
}

Now let's take a closer look at the Begin Data API.

Begin Data API

The Begin Data API consists of three primary methods: get, set, and destroy; and three helper methods: incr, decr, and count.

Each Begin Data method operates asynchronously, accepting an optional callback and returning a Promise.

Read documents

data.get()

As you'd imagine, data.get() is responsible for getting documents.

data.get() can get a single document, batch get multiple documents, or get an entire table.

Syntax

data.get(params[, callback])[Promise]


Get a single document

Get a single document by passing an Object containing:

  • table - String (required)
  • key - String (required)
// Basic example of getting a single document
let table = 'greetings'
let key = 'Japanese'
let doc = await data.get({table, key})

Get multiple documents

Get multiple documents by passing an Array containing:

  • One or more Objects, each containing:
    • table - String (required)
    • key - String (required)
// Basic example of getting multiple documents
let table = 'greetings'
let greetings = await data.get([
  {table, key: 'Māori'},
  {table, key: 'Swahili'},
  {table, key: 'Japanese'},
])

Get an entire table

Get an entire table by passing an Object containing:

  • table - String (required)
  • limit - Number
    • Limit the number of documents to be returned
  • cursor - String
    • If your table contains many documents (or a greater number of documents than your limit), it will return a cursor
// Basic example of getting an entire table
let table = await data.get({table:'greetings'})

If your table contains many documents, it will paginate and return a cursor, on which you can key your next query. For example:

let table = 'greetings'
let result = await data.get({table, limit: 3})

console.log(result, result.cursor)
// Logs:
//
// [{ table, key: 'Māori', greeting: 'Kia ora' },
//  { table, key: 'Swahili', greeting: 'Hujambo' },
// { table, key: 'Japanese', greeting: 'Kon'nichiwa' }
// ] 
// 
// and 
// 'eyJziJzY29wZUlELCJkYX9jYWwidW50RhSUQiOdGFnaW5nI21vIjoibGYWlucyNsa3JMV21PVWsifQ==' 
//

Create & update documents

data.set()

data.set() is responsible for creating new documents, and updating existing ones.

data.set() can operate on a single document, or batch up to 25 documents.

A single data.set() request cannot exceed 10KB.

Your supplied data can be any quantity of the following supported types:

  • Number
  • String
  • Binary
    • Must be base64 encoded
  • Boolean
  • Null
  • Array
  • Object

Syntax

data.set(params[, callback])[Promise]


Set a single document

Set a single document by passing an Object containing:

  • table - String (required)
  • key - String
    • If no key is supplied, Begin Data will automatically supply a pseudo-random, unique, immutable key
  • Your data
// Basic example of getting a single document
let table = 'greetings'
let key = 'Japanese'
let greeting = `Kon'nichiwa`
await data.set({table, key, greeting})

Set multiple documents

Set one or more documents by passing an Array containing:

  • One or more Objects, each containing:
    • table - String (required)
    • key - String
      • If no key is supplied, Begin Data will automatically supply a pseudo-random, unique, immutable key
    • Your data
let table = 'greetings'
let greetings = [ 
  { table, key: 'Māori', greeting: 'Kia ora' },
  { table, key: 'Swahili', greeting: 'Hujambo' },
  { table, key: 'Japanese', greeting: `Kon'nichiwa` } ]
await data.set(greetings)

Destroy documents

data.destroy()

data.destroy() is responsible for destroying documents.

Valid data.destroy() calls require passing a one or more Objects containing a table and key; there is no limit to the number of documents a single call can destroy.

Syntax

data.destroy(params[, callback])[Promise]


Destroy a single document

Destroy a single document by passing an Object containing:

  • table - String (required)
  • key - String (required)
let table = 'bad vibes'
let key = 'Negativity'
await data.destroy({table, key})

Destroy multiple documents

Destroy one or more documents by passing an Array containing

  • One or more Objects, each containing:
    • table - String (required)
    • key - String (required)
let table = 'bad vibes'
await data.destroy([
  { table, key: 'Pessimism' },
  { table, key: 'Anxiety' }
])

Helpers

Begin Data also surfaces a few handy helpers to make other common operations a bit easier, such as counting rows, and incrementing & decrementing Numbers.

data.count()

data.count() returns the count of a table's documents.

Syntax

data.count(params[, callback])[Promise]

  • params - Object (required)
    • table - String (required)
  • callback - Function

An example:

let table = 'greetings'
await data.get({table})
/* Returns:
42
*/

data.incr() & data.decr()

Syntax

data.incr(params[, callback])[Promise]

data.decr(params[, callback])[Promise]

  • params - Object (required)
    • table - String (required)
    • key - String (required)
    • Property to increment or decrement, must be a Number (required)
  • callback - Function

Examples:

let table = 'rain'
let key = `Wai'ale'ale`
let averageInches = 450

// Increment
await data.incr({table, key, averageInches})
/* Returns:
{ averageInches: 451 }
*/

// Decrement
await data.decr({table, key, averageInches})
/* Returns:
{ averageInches: 450 }
*/

TTL

Any document can be automatically expunged by setting a ttl value.

ttl is a Number corresponding to a specific future Unix epoch (expressed in seconds).

Documents will typically be automatically destroyed within 48 hours of the ttl expiring.

Tip: during the intervening time between ttl expiry and actual expunging, the document will still be available; if its ttl is mutated or unset, the document's new ttl state will be respected.

let table = 'mandalas'
let key = 'Tibetan'
let ttl = Date.now() - (60*60*24*7) // One week
await data.set({table, key, ttl})

Limits

  • Empty attributes are invalid and will produce errors. For example:

let table = 'accounts'
let key = 'dW50RhSUQiOdG'
let email = '' // Invalid
await data.set({table, key, email})
  • data.set() has a maximum batch size of 25 documents and 10KB per call.