Neurelo Schema Language (NSL)
Last updated
Last updated
The Neurelo Schema Language (NSL) is used to define entities, attributes, relationships, and constraints of a system. The language is based on the spec, with added capabilities to accurately describe the relationships and constraints within the schema.
Object - An object represents an entity in your data source. Each object consists of a name, a collection of properties, and constraints. Each object maps to a table (e.g. in PostgreSQL or MySQL) or a collection (e.g. in MongoDB) in your data source.
Properties - A property represents the fields of an object in your data source e.g. a column in a table (e.g. PostgreSQL or MySQL) or a key in a key:value pair (e.g. in MongoDB). The property definition indicates how a value should be formed and validated, how it maps to the data source object (table or collection) and, optionally, if it represents a relationship to another object.
Enum - An enum is a list of named values that can be used to limit the values that can be assigned to a property.
Constraints - A constraint represents additional definitions or rules that should be applied to an object, like a multi-property index.
Functions - A function can be used when assigning default values to an object’s property e.g. instead of having a hard-coded value, you can rely on your data source capabilities to generate a value for each record.
Relationships - A relationship defines how objects interact between them. They are defined on a per-property basis and specify information such as the cardinality of the relation.
Inner Object - An inner object is used to define a custom property schema, and can be reused across multiple objects, or even to define properties of other inner objects. Inner objects are not mapped to a table or collection. Currently they are only supported when using MongoDB (embedded documents).
The top level of a Neurelo Schema has the following format:
objects
must be specified in the top level, however, features
, enums
and innerObjects
are optional.
Each object is represented by a name and a set of properties:
Optionally, it can include a “sourceName” attribute, that indicates how an object is named in the data source:
And also an optional attribute “constraints” to indicate any extra indexes this entity may have in the data source:
The above example would create an index using multiple properties - id
and name
.
Each enum is represented by a name and a list of string values. Enums can be used to constrain the possible values for a property in a reusable way:
Properties define the values contained in an object e.g. in a column in a table (e.g. PostgreSQL or MySQL) or a key in a key:value pair (e.g. in MongoDB). Each property is defined by multiple attributes. These attributes define how the values for the property should be formed and how they map to the underlying data source.
Most of the properties accept the following attributes:
description
- optional, string value to add any documentation about the property. Does not have an actual effect on how the property behaves. For example,
default
- optional, object value that defines either a hardcoded value or a function that generates a default value for the property. For example,
sourceType
- optional, string or array value to specify the underlying data source type for this property. For examples on sourceType
, refer to the respective property’s documentation.
sourceName
- optional, string value to specify how this property is named in the underlying data source. This is particularly useful in MongoDB where [_id
field describes a unique objectId
](https://www.mongodb.com/docs/v2.4/reference/object-id/), which is the primary key for every document. For example,
nullable
- optional, boolean value to specify if the property is nullable or not. By default, nullable is set as false which means it’s a required property. Here is example for setting nullable to true -
identifier
- optional, boolean value to specify if the property should be treated as a primary key in the underlying data source. For example,
unique
- optional, boolean value to specify if the property should be treated as a unique key in the underlying data source. For example,
Required attributes: type
Optional attributes: default
, sourceType
, description
, nullable
, sourceName
, identifier
, unique
default
Default value can be one of:
Default true
/false
value. For instance, "default": { "value": true }
.
dbgenerated
function. Refer to Function section for further details on this.
sourceType
boolean
Boolean
"sourceType": "Boolean"
BIT(1)
Bit
"sourceType": "Bit"
TINYINT(1)
TinyInt
"sourceType": "TinyInt"
bool
Bool
"sourceType": "Bool"
Required attributes: type
Optional attributes: format
, default
, sourceType
, description
, nullable
, sourceName
, identifier
, unique
default
String supports a wide range of defaults:
Default string value. For instance, "default": { "value": "SomeValue" }
.
dbgenerated
, auto
, cuid
, and uuid
functions. Refer to Function section for further details on these.
sourceType
text
Text
"sourceType": "Text"
Default
varbit
VarBit
"sourceType": "VarBit"
uuid
Uuid
"sourceType": "Uuid"
xml
Xml
"sourceType": "Xml"
inet
Inet
"sourceType": "Inet"
citext
Citext
"sourceType": "Citext"
point
Point
"sourceType": "Point"
bit(n)
Bit
"sourceType": "Bit"
"sourceType": ["Bit", 5]
String form defaults length to 1. Array form is used to specify specific length.
char(n)
Char
"sourceType": "Char"
"sourceType": ["Char", 5]
String form defaults length to 1. Array form is used to specify specific length.
varchar(n)
VarChar
"sourceType": "VarChar"
"sourceType": ["VarChar", 5]
String form allows any length. Array form is used to specify max length.
TEXT
Text
"sourceType": "Text"
TINYTEXT
TinyText
"sourceType": "TinyText"
MEDIUMTEXT
MediumText
"sourceType": "MediumText"
LONGTEXT
LongText
"sourceType": "LongText"
CHAR(n)
Char
"sourceType": "Char"
"sourceType": ["Char", 5]
String form defaults length to 1. Array form is used to specify specific length.
VARCHAR(n)
VarChar
"sourceType": "VarChar"
"sourceType": ["VarChar", 5]
Default. String form defaults to max length 80. Array form is used to specify max length.
String
String
"sourceType": "String"
Default
ObjectId
ObjectId
"sourceType": "ObjectId"
Required for BSON id fields.
Required attributes: type
Optional attributes: default
, sourceType
, description
, nullable
, sourceName
, identifier
, unique
default
Default value can be one of:
Default integer value. For instance, "default": { "value": 0 }
.
dbgenerated
function. Refer to Function section for further details on this.
sourceType
integer
Integer
"sourceType": "Integer"
Default
smallint
SmallInt
"sourceType": "SmallInt"
oid
Oid
"sourceType": "Oid"
TINYINT
TinyInt
"sourceType": "Boolean"
TINYINT UNSIGNED
UnsignedTinyInt
"sourceType": "UnsignedTinyInt"
SMALLINT
SmallInt
"sourceType": "SmallInt"
SMALLINT UNSIGNED
UnsignedSmallInt
"sourceType": "UnsignedSmallInt"
MEDIUMINT
MediumInt
"sourceType": "MediumInt"
MEDIUMINT UNSIGNED
UnsignedMediumInt
"sourceType": "UnsignedMediumInt"
INT
Int
"sourceType": "Boolean"
Default
INT UNSIGNED
UnsignedInt
"sourceType": "UnsignedInt"
YEAR
Year
"sourceType": "Year"
int
Int
"sourceType": "Int"
Default. 32-bit integer
long
Long
"sourceType": "Long"
64-bit integer
Required attributes: type
, format
Optional attributes: default
, sourceType
, description
, nullable
, sourceName
, identifier
, unique
As big int is a special kind of string, to specify the usage of big int, "format": "bigInt"
is required.
default
Default value can be one of:
Default big int value. For instance, "default": { "value": 0 }
.
dbgenerated
function. Refer to Function section for further details on this.
sourceType
bigint
BigInt
"sourceType": "BigInt"
Default
BIGINT
BigInt
"sourceType": "BigInt"
Default
BIGINT UNSIGNED
UnsignedBigInt
"sourceType": "UnsignedBigInt"
long
BigInt
"sourceType": "BigInt"
Default
Required attributes: type
, format
Optional attributes: default
, sourceType
, description
, nullable
, sourceName
, identifier
, unique
As float is a special kind of number, to specify the usage of float, "format": "float"
is required.
default
Default value can be one of:
Default number value. For instance, "default": { "value": 0.0 }
.
dbgenerated
function. Refer to Function section for further details on this.
sourceType
double precision
DoublePrecision
"sourceType": "DoublePrecision"
Default
real
Real
"sourceType": "Real"
FLOAT
Float
"sourceType": "Float"
DOUBLE
Double
"sourceType": "Double"
Default
double
Double
"sourceType": "Double"
Default
Required attributes: type
, format
Optional attributes: default
, sourceType
, description
, nullable
, sourceName
, identifier
, unique
As decimal is a special kind of string, to specify the usage of decimal, "format": "decimal"
is required with "type": "string"
.
default
Default value can be one of:
Default decimal value. NSL matches decimal values with an optional minus sign, allowing for both integer and decimal parts. For instance, some strings that would match are: 123
, -45
, 0.314
, .56
, -123.456
. A default value can be specified as "default": { "value": 0 }
.
dbgenerated
function. Refer to Function section for further details on this.
sourceType
money
Money
"sourceType": "Money"
decimal(p, s)
Decimal
"sourceType": "Decimal"
"sourceType": ["Decimal", 3, 1]
Default. String form allows for unconstrained precision. Array form is used to specify the precision and scale.
DECIMAL(p, s)
Decimal
"sourceType": "Decimal"
"sourceType": ["Decimal", 3, 1]
Default. String form allows for unconstrained precision. Array form is used to specify the precision and scale.
decimal
Decimal128
"sourceType": "Decimal128"
Default
Required attributes: type
and format
Optional attributes: default
, sourceType
, description
, nullable
, sourceName
, identifier
, unique
date: 4 digit full year “-” 2 digit month “-” 2 digit day
For example, 9th January 2023 is represented as 2023-01-09
time: partial-time time-offset
partial-time
- hour ":" minute ":" second
time-offset
: "Z" / time-numoffset
, where time-numoffset
is ("+" / "-") hour-offset ":" minute-offset.
For example, 4:30 pm with a time offset of 15 minutes is represented as 16:30:00+00:15
date-time
: date "T" time
For example, 12:30 pm on 4th July 1990 can be represented as 1990-07-04T12:30:00Z
. Here, the Z
suffix denotes a UTC offset of 00:00.
Note that the letters T
and Z
used in the date/time syntax must always be upper case.
Our APIs currently only accept complete timestamps. This means you must follow the date-time
format (yyyy-mm-ddTHH:MM:SSZ
) specified above, even if your underlying data source type is just a date
or time
type.
default
Date Time supports a wide range of defaults:
Default date-time value. For instance, "default": { "value": "2024-01-01T12:00:00Z", "format": "date-time" }
.
now
and dbgenerated
functions. Refer to Function section for further details on these.
sourceType
date
Date
"sourceType": "Date"
timestamp(n)
Timestamp
"sourceType": "Timestamp"
"sourceType": ["Timestamp", 3]
Default. String form defaults to max 6 digits of precision. Array form is used to specify precision.
timestamptz(n)
Timestamptz
"sourceType": "Timestamptz"
"sourceType": ["Timestamptz", 3]
String form defaults to max 6 digits of precision. Array form is used to specify precision.
time(n)
Time
"sourceType": "Time"
"sourceType": ["Time", 3]
String form defaults to max 6 digits of precision. Array form is used to specify precision.
timetz(n)
Timetz
"sourceType": "Timetz"
"sourceType": ["Timetz", 3]
String form defaults to max 6 digits of precision. Array form is used to specify precision.
date
Date
"sourceType": "Date"
DATETIME(n)
DateTime
"sourceType": "DateTime"
"sourceType": ["DateTime", 3]
Default. String form defaults to max 6 digits of precision. Array form is used to specify precision.
TIME(n)
Time
"sourceType": "Time"
"sourceType": ["Time", 3]
String form defaults to max 6 digits of precision. Array form is used to specify precision.
TIMESTAMP(n)
Timestamp
"sourceType": "Timestamp"
"sourceType": ["Timestamp", 3]
String form defaults to max 6 digits of precision. Array form is used to specify precision.
date
Date
"sourceType": "Date"
timestamp
Timestamp
"sourceType": "Timestamp"
Default
Required attributes: type
and format
Optional attributes: default
, sourceType
, description
, nullable
, sourceName
, identifier
, unique
As bytes is a special kind of string, to specify the usage of bytes, "format": "bytes"
is required.
default
Default value can be one of:
Default byte value. For instance, "default": { "value": "V2VsY29tZSB0byBOZXVyZWxv" }
.
dbgenerated
function. Refer to Function section for further details on this.
sourceType
bytea
ByteA
"sourceType": "ByteA"
Default
BIT(1)
Bit
"sourceType": "Bit"
BINARY
Binary
"sourceType": "Binary"
VARBINARY
VarBinary
"sourceType": "VarBinary"
TINYBLOB
TinyBlob
"sourceType": "TinyBlob"
MEDIUMBLOB
MediumBlob
"sourceType": "MediumBlob"
BLOB
Blob
"sourceType": "Blob"
LONGBLOB
LongBlob
"sourceType": "LongBlob"
Default
binData
BinData
"sourceType": "BinData"
Default
Required attributes: type
and format
Optional attributes: default
, sourceType
, description
, nullable
, sourceName
, identifier
, unique
As a JSON type can itself support a number of basic types, its type
is represented as ["array", "boolean", "integer", "number", "object", "string"]
. Furthermore, format
is required to be of type json
.
default
Default value can be one of:
Default JSON value. For instance, "default": { "value": ["apple gardens", "strawberry fields", "vineyards"] }
.
dbgenerated
function. Refer to Function section for further details on this.
sourceType
json
Json
"sourceType": "Json"
jsonb
JsonB
"sourceType": "JsonB"
Default
JSON
Json
"sourceType": "Json"
Default
In MongoDB, json
is used indicate the flexible property type and that multiple types are supported for that property
Properties referencing an enum can be used to constrain its possible values to the ones defined in the enum.
The $ref
property is used to reference a specific part of the schema by assigning it a value containing the path to the referenced part:
The example above is referencing Rating
enum defined in the Enums
section.
Optionally, references to enums can define a default value for the property.
Required attributes: type
and items
Optional attributes: description
and sourceName
An array field can be represented by specifying a "type": "array"
, followed by the shape of the individual items the array will contain:
Note that sourceType
can be specified in the items
if necessary.
A reference in an object represents a relationship between the two of them. The relation
property is used to indicate relationships between objects in the schema definition.
The relation
property contains the following attributes:
attrKey - string or array of strings with the name of the object properties that contain the references to the foreign object.
foreignAttrKey - string or array of strings with the name of the foreign object properties that should match the ones defined in attrKey
.
name - optional, used to disambiguate when multiple relationships between the same models are present.
sourceName - optional, the name that should be used in the datasource for the foreign key index
onUpdate - optional, side effect to use when a parent model is updated. Defaults to NoAction.
onDelete - optional, side effect to use when a parent model is deleted. Defaults to NoAction
.
The actions supported by onUpdate
and onDelete
are:
Restrict
: Prevents updation/deletion if any child model’s records exist.
NoAction
: Similar to Restrict
however the functionality of NoAction
depends on the database being used. For instance,
MySQL: For MySQL, [NoAction
is equivalent to Restrict
](https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html#foreign-key-referential-actions).
MongoDB: When a parent model’s record is updated/deleted, the child model’s records remain as is.
Cascade
: Updating/deleting records from the parent model automatically triggers updation/deletion of corresponding records referenced in the child model.
SetNull
: After updating/deleting record from the parent model, the corresponding records referenced in the child model are set to Null
.
SetDefault
: After updating/deleting record from the parent model, the corresponding records referenced in the child model are set to their default values.
In the following example we have two objects: authors and author_details. The author_details object contains the relationship definition, as it is the one that has the author_id foreign key property. On the other hand, the authors object only contains a property with items referencing the author_details object.
In the following example we have two objects: authors and books. The books object contains the relationship definition, as it is the one that has the author_id foreign key property. On the other hand, the authors object only contains an array property with items referencing the books object.
In the following example we have two objects: books and libraries. A book can be found in many libraries, and each library contains many books. To define this type of relationship, where we are only interested in whether or not the records are related, we can use an implicit many to many definition.
Same scenario as the implicit version, but this time we need to keep track of additional information in the many to many pivot table, like the amount of books each library has purchased.
Functions can be used to generate the default value for a property. The supported functions are:
auto - Only available for MongoDB. Generates an ObjectId.
autoincrement - Generates an automatically incremented integer value.
cuid - Generates a string value based on the CUID spec.
uuid - Generates a string value based on the UUID spec.
now - Generates a Date Time value with the current data source timestamp.
dbgenerated - Generates a value by executing the provided “rawDbValue”.
rawDbValue
’s value is a database function. For instance, in PostgreSQL, gen_random_uuid()
returns a random UUID that can be used for primary key values.
Functions can be used as follows:
An identifier constraint can be used to define a multi-property primary key index for an object:
The optional “alias” property will be used in Neurelo’s APIs to allow filtering by all the properties of this constraint.
The optional “sourceName” property indicates how this index constraint is named in the data source.
A unique constraint can be used to define a multi-property unique index for an object:
The optional “alias” property will be used in Neurelo’s APIs to allow filtering by all the properties of this constraint.
The optional “sourceName” property indicates how this index constraint is named in the data source.
NOTE: The “sort” property is not supported within a unique constraint.
An index constraint can be used to define a single or multi-property index for an object:
The optional “alias” property will be used in Neurelo’s APIs to allow filtering by all the properties of this constraint.
The optional “sourceName” property indicates how this index constraint is named in the data source.
The optional “sort” property indicates the order in which the entries of this index will be stored in the data source.
The optional “length” property indicates the maximum length of the value to be indexed. Only available for MySQL.
The optional “kind” property indicates the type of index to be used in the data source. Defaults to “BTree”. Available options are: Hash, Gist, SpGist, Gin, Brin. Only available for PostgreSQL.
Only available for MongoDB. Inner Objects are defined in an almost identical way as objects, with the difference that the cannot have identifier or unique properties, nor constraints.
Inner objects can be used to describe complex schemas that can be reused across multiple objects properties via references. These properties will be represented in the underlying database as embedded documents.
Features are extensions to the schema.
For a guide on using this feature, seeUser Auth. To enable the feature you just have to specify the version (currently "1"
)
By default, Big Int maps to , , and . See sourceType
sub-section for further details.
For date time, the format supported is date-time
. This is derived from , in accordance with the JSON schema standard.
PostgreSQL: , NoAction
behaves similar to Restrict
except NoAction
allows the check to be deferred until later in the transaction, whereas Restrict
does not.