Data model
A data model describes and organizes various data elements within an app and standardizes how various data elements relate to one another.
Syntax overview
Imagine allows you to represent your app's data model using the following structure and syntax:
Example
As an example of a data model, let's take a fictional music app, Musica that has the concepts of a Musician and an Album.
Each Musician has the following fields:
- first name, which is a string that is less than 100 characters, and we want this field to be the unique identifier of the Musician
- last name, which is a string that is less than 100 characters
- age, which is a number between the range 10 and 100
Each Album has the following fields:
- album name, which is a string that is less than 200 characters, and we want this field to the unique identifier of the Album
- release date and time, which is the date and time an album is released
- no. of songs, which is number between 0 and 50
Also, a Musician may have many Albums as a lead vocalist.
In this example, the concepts of Musician and Album, each of their fields, the properties of each of the fields, as well as how Musician and Album relate to each other, all together constitute the Musica's data model.
Representation in Imagine syntax
The Musica data model would be represented in Imagine's syntax as follows:
Settings
There are no settings currently required for the data model domain.
Domain-specific syntax
Imagine's Domain-specific syntax for the data model domain supports two main modules: Model and Relation.
We will describe the various elements in each module in detail below.
Model
The Model module allows you to define a new data model in your app. This concept is analogous to a class in programming languages or table in a database.
The various elements of a Model are as follows:
Model-name
Each Model is followed by a unique user-selected <model-name>
for that Model. Please see this for rules on selecting a <model-name>
.
In the example below, Musician and Album are <model-names>
.
Field-name
Each Model has various fields which describe various attributes of the Model, and each field has a user-selected field-name
. Please see this for rules on selecting a field-name
In the example below, first-name, last-name and age are field-names
for the different fields in the Model Musician.
Field-type
Each field is of a certain <field-type>
, which is one of:
- string - a string of characters
- integer - a positive or negative whole number
- datetime - date and time
- float - a positive or negative number with a decimal point
- boolean - a boolean value of either
True
orFalse
In the example below, the Model Album contains the following fields
- album_name of
<field-type>
string - release_date_time of
<field-type>
datetime - num_songs of
<field-type>
integer - rating of
<field-type>
float - bestseller of
<field-type>
boolean
Field-property, Field-property-value
Each <field-type>
can have various <field-properties>
and associated <field-property-values>
that govern the behaviour of that field. We have outlines supported <field-properties>
and <field-property-values>
below:
primary-key
- This
<field-property>
can be used for string and integer<field-types>
. - This allows a field to be tagged as the unique identifier for a model.
- Each model requires at least one field to be given a primary-key
<field-property>
. - The primary key
<field-property>
does not have an associated<field-property-value>
. - This is similar to the concept of primary key in MySQL and primary key in PostgreSQL.
- This
max-length
This
<field-property>
can be used for the string<field-types>
.This allows you to specify the maximum allowable length for a field instance where the
<field-types>
is stringIn the example below, the first-name of the model Musician is allowed to have a maximum length of 100 characters.
```Model Musician {first_name string [max-length 100]}```
choice
This
<field-property>
can be used for the string<field-type>
.This allows you to specify the maximum specific value choices that can be selected in for a field.
In the example below, the color of the model Shoes can be one of red, blue or green.
Model Shoes {color string [ choice ["red", "blue", "green"] ]}
range
This
<field-property>
can be used for the integer and float<field-types>
.This allows you to specify the allowable range for a field.
In the example below, the age of the model Musician is only allowed to have values in the range of 20 and 50 (where both 20 and 50 inclusive).
```Model Musician {age integer [range 20 50]}```For integer fields, float values may be used, meaning that the field should be in the appropriate range. That is,
age integer [range 20.5 50]
is equivalent toage integer [range 21 50]
.
min
This
<field-property>
can be used for the integer and float<field-types>
.This allows you to specify the minimum value for a field.
In the example below, the age of the model Musician is only allowed to have values that are 20 or higher.
```Model Musician {age integer [min 20]}```For integer fields, a float value may be used, meaning that the field should be greater than the ceiling of the number. That is,
age integer [min 0.5]
is equivalent toage integer [min 1]
.
max
This
<field-property>
can be used for the integer and float<field-types>
.This allows you to specify the maximum value for a field.
In the example below, the age of the model Musician is only allowed to have values that are 50 or lower.
```Model Musician {age integer [min 50]}```For integer fields, a float value may be used, meaning that the field should be smaller than the floor of the number. That is,
age integer [max 90.5]
is equivalent toage integer [max 90]
.
unique
This
<field-property>
can be used for ALL<field-types>
.This allows a field to be tagged in a way that only one unique instance of that field.
The unique
<field-property>
does not have an associated<field-property-value>
.In the example below, using the unique
<field-property>
you can ensure that no two Musician instances can have the same social security number:```Model Musician {Social_security_number integer [primary-key, unique]}```
nullable
This
<field-property>
can be used for ALL<field-types>
.This allows a field instance to be null.
The nullable
<field-property>
does not have an associated<field-property-value>
.In the example below, using the nullable
<field-property>
for the age field allows this field to be left empty in an instance of the Musician model.```Model Musician {first_name string [max-length 100, primary-key]last_name string [max-length 100]age integer [range 10 100, nullable]}```
default
This
<field-property>
can be used for ALL<field-types>
.This allows a default value to be specified for the field.
The provided default value should be of the same type as the
<field-type>
.In the example below, we have chosen a default
<field-property>
with<field-property-value>
of red for the color field and of 20 for the size field in the Model Shoes.Model Shoes {color string [default "red"]size integer [default 10]}There are also some special default
<field-property-values>
you can use:auto-increment
- This is a special default value which allows automatic incrementing of an integer
<field-type>
. - This is similar to a database's concept of serial in PostgreSQL and auto_increment in MySQL.
- This is a special default value which allows automatic incrementing of an integer
now
- This is a special default value that assigns the current time as the value for a datetime
<field-type>
. - This is similar to a database's concept of current_timestamp` in MySQL and current_timestamp** in PostgreSQL.
- This is a special default value that assigns the current time as the value for a datetime
Example use:
Model Musician {id integer [default auto-increment, primary-key]last_seen datetime [default now]}
Relation
The Relation module allows you to define how any two Models are related in your app. This concept is analogous to relations in a database [ADD LINK].
We current support the many child models to one parent model relation in Imagine's syntax.
The various elements of a Relation are as follows:
relation-name
The relation-name
allows you to name the specific Relation that you are adding to the data model.
In the example below, albums_lead_vocalist is the relation-name
.
Please see this for rules on selecting a <relation-name>
.
child-model-name, parent-model-name
For two Models related as many child models to one parent model, <child-model-name>
refers to the <model-name>
of the child model, and <parent-model-name>
refers to the <model-name>
of the parent model.
In the example below, a Musician can have many Albums. Here, Album and Musician are both data models, where Album is the <child-model>
and Musician is the <parent-model>
.
child-relation-name, parent-relation-name
A <child-relation-name>
and <parent-relation-name>
allow you add a specific name to the child and the parent Models that are related.
In the example below, a lead_vocalist (who is a Musician) can have many albums (from the Album data model). Here, lead_vocalist is the <parent-relation-name>
and albums is the <child-relation-name>
.
Please see this for rules on selecting a <child-relation-name>
and <parent-relation-name>
.
parent-key, unique-parent-field-name
The <unique-parent-field-name>
is a unique identifier of the parent-model - it can be the field-name
of any field of a Model that has the field-property
unique.
If you don't specify a parent-key, the field-name
associated with the primary-key
in the parent model is used as default the parent-key
.
In the following example, 'id' is used as the default parent key.
Defining Relations allows you to access the relational data in your data model using your API as follows:
- albums for a lead vocalist using musician-instance.albums, where albums is the
<child-relation-name>
- the lead vocalist to which an Album belongs to using album-instance.lead_vocalist, where lead_vocalist is the
<parent-relation-name>
PS - here musician-instance and album-instance are used to described the specific instance of the musician (e.g. Pink Floyd) or the album (e.g. The Wall) that the API is trying to access.