@growsari/dbal
v2.1.0
Published
Database access layer
Downloads
446
Keywords
Readme
Database Access Layer
Database Access Layer (DBAL) is a wrapper for DynamoDB Client. It provides the basic create, read, update and delete (CRUD) functionality and lets you group data into an entity.
Installation and Basic Usage
Install the Database Access Layer
npm i @growsari/dbal
Require or import the package as Entity
const Entity = require('@growsari/dbal')
Before we could use it, the project must have the following environment variables
| ENV | Description | Default Value | Other Value | |---|---|---|---| | IS_OFFLINE | Flag for local development | false | true | | DB_ADAPTER | Database to be used | dynamodb | ~ | | DYNAMODB_ENDPOINT | DynamoDB endpoint | http://localhost:8000 | ~ | | TABLE_NAME | DynamoDB table name | ~ | ~ |
Create a new class and extend Entity
'use strict'
const Entity = require('@growsari/dbal')
class User extends Entity {
constructor() {
super()
this.attributes = {
email: [
'identifier'
],
group_id: [
'foreign'
]
}
this.sort = [
{
index: 'SortByCreatedAtIndex',
field: 'created_at'
},
{
index: 'SortByNameIndex',
field: 'name'
}
]
}
}
module.exports = User
Require User
entity and create item:
await User.create({
name: 'John Doe',
email: '[email protected]',
group_id: 'BDS45HX47I9CT'
})
// {
// "id": "659312a0-1b5c-11ea-a271-e732f3f9733b",
// "created_at": "2019-12-10T14:50:24.330Z",
// "updated_at": "2019-12-10T14:50:24.330Z",
// "name": "John Doe",
// "email": "[email protected]",
// "group_id": "BDS45HX47I9CT"
// }
Read item by:
await User.getById('659312a0-1b5c-11ea-a271-e732f3f9733b')
Update item by:
await User.updateById('659312a0-1b5c-11ea-a271-e732f3f9733b', {
name: 'John Doe II'
})
Delete item by:
await User.deleteById('659312a0-1b5c-11ea-a271-e732f3f9733b')
Update item by id based on condition options.
await User.updateByIdWithConditionOrFail('659312a0-1b5c-11ea-a271-e732f3f9733b', {name: 'John'}, ['AND', {name: {'!=': 'John Doe II'}}])
Entity Class Properties
These are the properties for configuring an entity
attributes
Lets you configure a special field in an item which implies uniqueness, foreign key and so on
| Value | Description | |---|---| | identifier | Creates a field with unique value within the entity | | foreign | Creates a foreign key (id in another microservice) | | namespace:field | Creates an identifier within a namespace (determined by field) |
Sample
this.attributes = {
[attribute_name] : [
'identifier',
'foreign',
'namespace:field'
]
}
sort
List of DynamoDB global secondary indexes (GSI) for data retrieval sorting
Entity Class Functions
These are the available functions for managing the data within an entity
async create(data)
async updateById(id, data)
async deleteById(id)
async bulkCreate(collection)
async bulkUpdate(collection)
async bulkDelete(collection)
async getById(id)
async getByIdOrFail(id)
async getByIdentifier(identifier, value)
async getByIdentifierWithinNamespace(namespace, identifier, value)
async getByIds(ids)
async getAll(first, after, sortBy, filterConditions)
async getAllByForeignKey(foreignKey, foreignValue, first, after, sortBy, filterConditions)
async search(query, rawQuery, fields, perPage, page, filters, sort)
async reindex()
async syncWithSearchEngine()
Sort By
A string which is composed of field
name and order
joined by |
.
const sortBy = 'name|asc'
await Product.getAll(first, after, sortBy, filterConditions)
Filter Conditions
NOTE: To effeciently use the filter conditions in terms of DynamoDB RCU and WCU, I recommend using it with getAll() API. If you can't avoid using it with getAllByForeignKey() API please use filter with the defined sort fields.
These are the recognized compound expressions:
AND
expression
Asserts that all of the subexpressions' conditions are satisfied.
const filterConditions = [
'AND',
{ name: 'Coke' },
{ is_available: true },
// more subexpressions
]
await Product.getAll(first, after, sortBy, filterConditions)
The above condition is equivalent to the following boolean expression:
name === 'COKE' && is_available === true && ...
OR
expression
Asserts that at least one of the subexpressions' condtions are satisfied.
const filterConditions = [
'OR',
{ name: 'Coke' },
{ brand: 'Coke' },
// more subexpressions
]
await Product.getAll(first, after, sortBy, filterConditions)
The above condition is equivalent to the following boolean expression:
name === 'COKE' || brand === 'Coke' || ...
NOT
expression
Asserts that at least one of the subexpressions' condtions are satisfied.
const filterConditions = [
'AND',
{ name: 'Coke' },
['NOT', { is_available: true }]
]
await Product.getAll(first, after, sortBy, filterConditions)
The above condition is equivalent to the following boolean expression:
name === 'COKE' && is_available !== true
Equal
expression
An object with one pair of key and value. The object's key represents the field
name. The object's value is also an object and it represents the condition where the condition's key is the operation
.
==
operation creates a condtion which is true if the field
is equal to the defined value
.
const filterConditions = { name: { '==': 'Coke' } }
// can be simplified to:
// const filterConditions = { name: 'Coke' }
await Product.getAll(first, after, sortBy, filterConditions)
NotEqual
expression
!=
operation creates a condtion which is true if the field
is not equal to the defined value
.
const filterConditions = { is_available: { '!=': false } }
await Product.getAll(first, after, sortBy, filterConditions)
LessThan
expression
<
operation creates a condtion which is true if the field
is less than to the defined value
.
const filterConditions = { available: { '<': 10 } }
await Product.getAll(first, after, sortBy, filterConditions)
LessThanOrEqualTo
expression
<=
operation creates a condtion which is true if the field
is less than or equal to the defined value
.
const filterConditions = { available: { '<=': 10 } }
await Product.getAll(first, after, sortBy, filterConditions)
GreaterThan
expression
>
operation creates a condtion which is true if the field
is greater than to the defined value
.
const filterConditions = { available: { '>': 10 } }
await Product.getAll(first, after, sortBy, filterConditions)
GreaterThanOrEqualTo
expression
>=
operation creates a condtion which is true if the field
is greater than or equal to the defined value
.
const filterConditions = { available: { '>=': 10 } }
await Product.getAll(first, after, sortBy, filterConditions)
Between
expression
between
operation creates a condtion which is true if the field
is between value[0]
and value[1]
.
const filterConditions = {
created_at: {
'between': ['2020-06-01T00:00:00.000Z', '2020-06-15T00:00:00.000Z']
}
}
await Product.getAll(first, after, sortBy, filterConditions)
In
expression
in
operation creates a condtion which is true if the field
is equal to an element the defined set of value
s.
const filterConditions = {
tags: {
'in': ['bottle', 'soda', 'promo', 'top_10', 'drink']
}
}
await Product.getAll(first, after, sortBy, filterConditions)
BeginsWith
expression
NOTE! This operation will only work with sort fields
beginsWith
operation creates a condtion which is true if the field
is a string and begins with or has a prefix of value
.
const filterConditions = { status: { 'beginsWith': 'active_' } }
await Product.getAll(first, after, sortBy, filterConditions)
Contains
expression
NOTE! This operation will only work with sort fields
contains
operation creates a condtion which is true if the field
contains the defined value
.
const filterConditions = { status: { 'contains': 'active' } }
await Product.getAll(first, after, sortBy, filterConditions)
Errors
| Code | Message | | --- | --- | | DBAL-001 | Database not supported | | DBAL-002 | Item not found for 'entity' entity | | DBAL-003 | Invalid pagination cursor | | DBAL-004 | Identifier 'field' must be unique | | DBAL-005 | Identifier 'field' within the namespace 'field' must be unique | | DBAL-006 | Sort key 'field' is not provided | | DBAL-007 | Invalid value for foreign key 'field' | | DBAL-008 | Duplicate entries in array as input is not allowed | | DBAL-009 | Invalid search engine setup |