Begin Data is an easy to use, fast, durable, highly scalable, fully managed, SSD-based key-value and document database that comes bundled with every Begin app.
Begin Data is easy to learn and simple to implement, and is designed to accommodate most general persistence use cases.
Here's a simple example of an HTTP 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 {
statusCode: 200,
type: 'text/html; charset=utf8',
body: `Hello ${account.name}!`
}
}
Begin Data documents have two mandatory properties:
table
- String (required)[a-zA-Z0-9.,:-/+?&=@]
key
- String[a-zA-Z0-9.,:-/+?&=@]
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 {
statusCode: 200,
type: 'text/html; charset=utf8',
body: `"Hello" in ${key} is: ${hello}!`
}
}
Now let's take a closer look at the 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 or returning a Promise.
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
.
data.get(params[, callback])
→ [Promise]
params
- Object or Array (required)
callback
- FunctionGet 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 by passing an array 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'},
])
table
Get an entire table
by passing an object containing:
table
- String (required)limit
- Numbercursor
- Stringtable
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
for use in your next query. For example:
let table = 'greetings'
let result = await data.get({table, limit: 3}) // Returns:
// [{ table, key: 'Māori', greeting: 'Kia ora' },
// { table, key: 'Swahili', greeting: 'Hujambo' },
// { table, key: 'Japanese', greeting: 'Kon'nichiwa' },
// cursor: 'eyJziJzY29wZUlELCJkYX9jYWwidW50RhSUQiOdGFnaW5nI21vIjoibGYWlucyNsa3JMV21PVWsifQ==']
The cursor is a string that indicates a position of the last document fetched. To use the cursor, pass it as the key in your next query. For example:
let table = 'greetings'
let result = await data.get({table, limit: 3}) // returns three documents, plus a cursor
let cursor = result.cursor // a string to indicate the position of the previous query
let nextPage = await data.get({table, cursor}) // returns the remaining documents
// { table, key: 'Chinese', greeting: 'Ni hao'}
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:
data.set(params[, callback])
→ [Promise]
params
- Object or Array (required)
callback
- FunctionSet a single document by passing an object containing:
table
- String (required)key
- Stringkey
is supplied, Begin Data will automatically supply a pseudo-random, unique, immutable key
// Basic example of getting a single document
let table = 'greetings'
let key = 'Japanese'
let greeting = `Kon'nichiwa`
await data.set({table, key, greeting})
Set one or more documents by passing an Array containing:
table
- String (required)key
- Stringkey
is supplied, Begin Data will automatically supply a pseudo-random, unique, immutable key
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)
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.
data.destroy(params[, callback])
→ [Promise]
params
- Object or Array (required)
callback
- FunctionDestroy 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 one or more documents by passing an Array containing
table
- String (required)key
- String (required)let table = 'bad vibes'
await data.destroy([
{ table, key: 'Pessimism' },
{ table, key: 'Anxiety' }
])
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.
data.count(params[, callback])
→ [Promise]
params
- Object (required)table
- String (required)callback
- FunctionAn example:
let table = 'greetings'
await data.count({table}) // Returns: 42
data.incr()
& data.decr()
data.incr(params[, callback])
→ [Promise]
data.decr(params[, callback])
→ [Promise]
params
- Object (required)table
- String (required)key
- String (required)callback
- FunctionThe following example assumes you have an attribute of 'averageInches' with a beginning value of 450 on the key of Wai'ale'ale
.
If that attribute does not exist, incrementing will begin at 0, and that attribute will be created.
let table = 'rain'
let key = `Wai'ale'ale`
// Increment
await data.incr({table, key, prop: 'averageInches'})
// Returns: { averageInches: 451 }
// Decrement
await data.decr({table, key, prop: 'averageInches'})
// Returns: { averageInches: 450 }
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() / 1000) + (60 * 60 * 24 * 7) // One week from now in seconds
await data.set({table, key, ttl})
data.set()
has a maximum batch size of 25 documents and 10KB per call.let table = 'accounts'
let key = 'dW50RhSUQiOdG'
let email = '' // Invalid
await data.set({table, key, email})
Your local Sandbox instantiates an in-memory version of Begin Data. You can start Sandbox by running the command arc sandbox
in the root of your project. You need to add the following to @tables
section to your app.arc
file to create the local instance of Begin Data.
app.arc
:
@tables
data
scopeID *String
dataID **String
ttl TTL