Skip to main content

String

Introduction

String is DynamoDB's String data type (marshalled as "S") for DynamoQL.

Define a String

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
default: randomUUID
},
password: String,
sex: {
type: String,
}
} as const);

Options

- primaryIndex

top-level only

boolean which markes attribute as HASH key and makes attribute as required, default is false.
A Schema can have only one primaryIndex.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
},
} as const);

- sortKey

top-level only

boolean which markes attribute as RANGE key and makes attribute as required, default is false.
A Schema can have only one sortKey.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
country: {
type: String,
primaryIndex: true,
},
city: {
type: String,
sortKey: true
}
} as const);

- LSI

top-level only

defines a Local Secondary Index.

LSI option is an object where you must provide:

  • indexName which should be unique across the Schema.
  • project which may be ALL | KEYS or string[] where strings are attriubute names defined in the Schema.
import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
},
firstname: {
type: String,
LSI: {
indexName: "firstname-index",
project: "ALL"
}
}
} as const);

- GSI

top-level only

defines a Global Secondary Index.

GSI option is an object where you must provide:

  • indexName which should be unique across the Schema.
  • project which may be ALL | KEYS or string[] where strings are attriubute names defined in the Schema.
import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
},
firstname: {
type: String,
GSI: {
indexName: "firstname-index",
project: "ALL"
}
}
} as const);

for composite table (HASH and RANGE) you must provide another attribute with GSI:

  • indexName which must be one of defined GSI indexName.
  • sortKey true.
import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
},
firstname: {
type: String,
GSI: {
indexName: "firstname-index",
project: "ALL"
}
},
lastname: {
type: String,
GSI: {
indexName: "firstname-index",
sortKey: true
}
}
} as const);

- required

boolean which makes attribute as required or optionnal, default is false when type is defined with an Object.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
default: randomUUID
},
password: {
type: String,
required: true
}
} as const);

- default

To set a default value for an attribute use default option.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
default: randomUUID
},
sex: {
type: String,
default: "unknown"
}
} as const);

With this configuration when you put an Item into your table, your Item will contain password attribute with 5 as value.

default must be a String.
Otherwise it will throw an error during dev time and runtime.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
default: randomUUID
},
password: {
type: String,
default: true // DynamoQLInvalidTypeException: "password" expected to be "S" received "BOOL".
}
} as const);

default can also be a (async) function which accepts one argument (put Item value) and must return a String.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
default: randomUUID
},
sex: {
type: String,
default: (item: Record<string, any>)=> {
return "unknown"
}
}
} as const);

- validate

validate option allows you to manually validate provided value in put and update commands.
To return an error you should return a string which explains value invalidity. Any other returned value is considered as valid.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
default: randomUUID
},
email: {
type: String,
validate: (self: string)=> {
if(!self.includes("@")) {
return "Invalid e-mail"
}
}
}
} as const);

- minLength

define minimum string length.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
default: randomUUID
},
password: {
type: String,
min: 12
}
} as const);

- maxLength

define maximum string length.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
default: randomUUID
},
password: {
type: String,
max: 89
}
} as const);

- enum

define accepted values.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
default: randomUUID
},
sex: {
type: String,
enum: ["female", "male", "unknown"]
}
} as const);

- trim

boolean to trim or not provided value.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
default: randomUUID
},
firstname: {
type: String,
trim: true
}
} as const);

- lowercase

boolean to lowercase or not provided value.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
default: randomUUID
},
firstname: {
type: String,
lowercase: true
}
} as const);

- uppercase

boolean to uppercase or not provided value.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
default: randomUUID
},
firstname: {
type: String,
uppercase: true
}
} as const);

- capitalize

boolean to capitalize or not provided value.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
default: randomUUID
},
firstname: {
type: String,
capitalize: true
}
} as const);

- set

To modify a value before storing it use set option.
set (async) function accepts 3 arguments:

  1. self provided value.
  2. item entier put Item object.
  3. setterInfo an optionnal value provided inside in put, batchPut, batchWrite, transactWrite command's options.

set will not be called if attribute doesn't exists in put Item object.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
default: randomUUID
},
password: {
type: String,
set: (self: string, item: Record<string, any>, setterInfo?: any)=> {

if(setterInfo?.generateHash) {
return functionToGenerateHash(self)
}

return self
}
}
} as const);

- get

When reteving an Item we can transform field's value with get option.

get (async) function accepts 3 arguments:

  1. self retrieved value.
  2. item entier retrieved Item object.
  3. getterInfo an optionnal value provided inside get, batchGet, transactGet, query, scan command's options.

get can return anything.
get will not be called if attribute doesn't exists in stored Item.

import { Schema } from "dynamoql";
import { randomUUID } from "crypto";

const userSchema = new Schema({
id: {
type: String,
primaryIndex: true,
default: randomUUID
},
password: {
type: String,
get: (self: String, item: Record<string, any>, getterInfo?: any)=> {
if(getterInfo?.forFrontend) {
return undefined
}
return self
}
}
} as const);
info

get returned value's type affects Item type when retriving Item(s) from DynamoDB.

- description

add any information to the Schema for your personal usage.

Condition expression

Condition expression are not part of Schema but they are based on your defined Schema.
They are used in various DynamoDB operations to check for some condition(s).
DynamoQL supports all DynamoDB Condition expression.

- equals

{
firstname: "John"
}

or

{
firstname: {
$eq: "John"
}
}

- not equals

{
firstname: {
$neq: "John"
}
}

- attribute exists

$exists can be true or false.

{
firstname: {
$exists: true
}
}

- includes

Checks if stored string contains provided value.

{
firstname: {
$includes: "oh"
}
}

- string length

Checks for stored string's length.

{
firstname: {
$size: 1
}
}

$size can also be any valid numeric comparison operator.

{
firstname: {
$size: {
$gt: 0
}
}
}

Possible operators are $eq, $neq, $gt, $gte, $lt, $lte, $in, $between.

- attribute type

Checks for stored attribute type.

{
firstname: {
$type: String
}
}

$type can be String, Number, Boolean, Null, Buffer, Object, Array, or {type: Set, items: String | Number | Buffer }

- starts with

Checks if stored string starts with provided value.

{
firstname: {
$startsWith: "Jo"
}
}

- greather than

Lexicographically compares if stored string is greather than provided value.

{
firstname: {
$gt: "Joh"
}
}

- greather than or equal

Lexicographically compares if stored string is greather than or equal provided value.

{
firstname: {
$gte: "Joh"
}
}

- little than

Lexicographically compares if stored string is little than provided value.

{
firstname: {
$lt: "Joh"
}
}

- little than or equal

Lexicographically compares if stored string is little than or equal provided value.

{
firstname: {
$lte: "Joh"
}
}

- between

Lexicographically compares if stored string is greather than or equal value1 AND is little than or equal value2.

{
firstname: {
$between: [value1, value2]
}
}

- in

Checks if provided array includes stored string.

{
firstname: {
$in: ["Steve", 214, "Sara", false, "John", "Mike", null]
}
}

- AND

Checks for multiple conditions. Condition is valid if ALL specified conditions are satisfied.

{
firstname: {
$and: [
{
$size: 4
},
{
$includes: "oh"
}
]
}
}

shorthand style

{
firstname: {
$size: 4,
$includes: "oh"
}
}

- OR

Checks for multiple conditions. Condition is valid if at least one of specified conditions is satisfied.

{
firstname: {
$or: [
{
$size: 6
},
{
$includes: "oh"
}
]
}
}

- NOT

Condition is valid if specified condition is NOT satisfied.

{
firstname: {
$not: {
$includes: "admin"
}
}
}

$not accepts any Condition expression.

When multiple conditions are provided inside $not: {} they are considered as $and condition.

{
firstname: {
$not: {
$size: 6,
$includes: "admin"
}
}
}

longhand equivalent is:

{
firstname: {
$not: {
$and: [
{
$size: 6
},
{
$includes: "admin"
}
]
}
}
}

Update expressions

Like Condition expression, Update expressions are not part of Schema, but they are based on defined Schema.

Update expressions are used in update, transactUpdate and transactWrite operations.

DynamoQL supports all DynamoDB update operations.

- set

$set replaces stored string by provided string.

{
firstname: {
$set: "John"
}
}

shorthand version is

{
firstname: "John"
}

- if not exists

$ifNotExists sets provided string if attribute do not exists in stored item.
$ifNotExists dont affects Condition expression and is attribute specific.
If attribute exists, stored value stays unchanged.

{
firstname: {
$ifNotExists: "John"
}
}