Models
In this part we can learn how to create own models and start to build your back-end project. there are several options to create your models and modify them.
According to loopback model definition rules:
A LoopBack model is a JavaScript object with both Node and REST APIs that represents data in backend systems such as databases. Models are connected to backend systems via data sources. You use the model APIs to interact with the data source to which it is attached.
Additionally, you can add functionality such as validation rules and business logic to models.
Every LoopBack application has a set of predefined built-in models such as User, Role, and Application. You can extend built-in models to suit your application’s needs.Additionally, you can define your own custom models specific to your application. You can create LoopBack models several different ways:
- With the command-line tool, by using the LoopBack model generator.
- From an existing relational database, by using model discovery.
- From free-form data in NoSQL databases or REST APIs by using instance introspection.
These methods all create a Model definition JSON file that defines your model in LoopBack.
You can also create and customize models programmatically using the LoopBack API, or by manually editing the model definition JSON file.In most cases, you shouldn’t need to use those techniques to create models, but you generally will use them to modify and customize models.
Once you’ve created a model, you can customize it to suit your needs, and also add data validation and create relationships among models.
Models come with a standard set of REST endpoints for create, read, update, and delete (CRUD) operations on model data. You can customize a model’s endpoints; see Exposing models over REST.
Create Model
- Using the model generator :
The easiest way to create a new model is with the model generator.
just run below command on projectDirectory/api
$ lb model <modelName>
When creating a new model, the generator will prompt you for the properties in the model. Subsequently, you can add more properties to it using the property generator.
When you create a model (for example, called “myModel”), the tool:
- Creates
/api/common/models/myModel.json
, the model definition JSON file. - Creates
/api/common/models/myModel.js
, where you can extend the model programmatically. For example to add remote methods. See Adding application logic for more information. - Adds an entry to
/api/server/model-config.json
for the model, specifying the model’s data source. See model-config.json for more information.
After you create a model, you can add more properties with the property generator.
$ lb property
The tool will prompt you to choose the model to which you want to add the property, along with the other property settings (as before). Then, it will modify the model definition JSON file accordingly.
- Using the model json file
LoopBack adds the settings in the the model JSON file to those of the base model. follow the below steps to create your manual model.
- Adds an entry to
/api/server/model-config.json
for the model, specifying the model’s data source. append your model as json item end of this file like below:
"myModel": { "dataSource": "myDb", "public": true }
dataSource: Name of the data source to which the model is connected. Must correspond to a data source defined in datasources.json.
public: Whether the model API is exposed. If true, then the model is exposed over REST. Does not affect accessibility of Node API.
- Creates
/api/common/models/myModel.json
, the model definition JSON file.
{ "name": "myModel", "base": "PersistedModel", "strict": false, "idInjection": false, "options": { "validateUpsert": true }, "properties": { "id": { "type": "string", "id": true, "index": true }, "propertyName": { "type": "string", "required": true } }, "validations": [], "relations": {}, "acls": [], "methods": {} }
- Creates
/api/common/models/myModel.js
, where you can extend the model programmatically.
'use strict'; module.exports = function(myModel) { };
after create your models you should restart your server script by run npm run service.
In Model Config ( next section ) you can reach to the information about how to set properties, options, validations, relations and methods.
In general, use
PersistedModel
as the base model when you want to store your data in a database using a connector such as MySQL or MongoDB. UseModel
as the base for models that don’t have CRUD semantics, for example, using connectors such as SOAP and REST.
For example, here is an excerpt from a customer.json
file that extends the built-in User model to define a new Customer model:
{ "name": "Customer", "base": "User", "idInjection": false, ...
In general, you can extend any model this way, not just the built-in models.
Important:
Currently you cannot modify a built-in model’s required properties. If you need to do this, then create your own custom model as a replacement instead.
Models Config
The LoopBack model generator creates a model JSON file for each model in either the server/models
or the common/models
directory (depending on whether the model is server-only or defined on both server and client). The file is named *model-name*``.json
, where *model-name*
is the model name; for example, customer.json
. The model JSON file defines models, relations between models, and access to models.
Note:
The LoopBack model generator automatically converts camel-case model names (for example MyModel) to lowercase dashed names (my-model). For example, if you create a model named “FooBar” with the model generator, it creates filesfoo-bar.json
andfoo-bar.js
incommon/models
. However, the model name (“FooBar”) will be preserved via the model’s name property.
For example, here is an excerpt from a model definition file for a customer model that would be in /common/models/customer.json
:
{ "name": "Customer", // See Top-level properties below "description": "A Customer model representing our customers.", "base": "User", "idInjection": false, "strict": true, "options": { ... }, // See Options below - can also declare as top-level properties "properties": { ... }, // See Properties below "hidden": [...], // See Hidden properties below "validations": [...], // See Validations below "relations": {...}, // See Relations below "acls": [...], // See ACLs below "scopes": {...}, // See Scopes below "indexes" : { ...}, // See Indexes below "methods": [...], // See Methods below "remoting": { "normalizeHttpPath": true }, "http": {"path": "/foo/mypath"} }
Top-level properties
Properties are required unless otherwise designated.
Property | Type | Default | Description |
---|---|---|---|
name | String | None | Name of the model. |
base | String | None | Name of another model that this model extends. The model will “inherit” properties and methods of the base model. |
description | String | None | Optional description of the model. |
idInjection | Boolean | true | Whether to automatically add an id property to the model:
See ID properties for more information. The |
options | Object | N/A | JSON object that specifies model options. See Options below. |
plural | String | Plural of name property | Plural form of the model name. |
properties | Object | N/A | JSON object that specifies the properties in the model. See Properties below. |
forceId | Boolean | true | If true, prevents clients from setting the auto-generated ID value manually. |
http.path | String | None | Customized HTTP path for REST endpoints of this model. |
relations | Object | N/A | Object containing relation names and relation definitions. See Relations below. |
remoting | Boolean | false | If true , in HTTP paths, converts:
Does not affect placeholders (for example “:id”). For example, “MyClass” or “My_class” becomes “my-class”. |
strict | Boolean | false .If the data source is backed by a relational database, then default is true . | Specifies whether the model accepts only predefined properties or not. One of:
|
Options
The options
key specifies advanced options, for example data source-specific options.
Property | Type | Description |
---|---|---|
validateUpsert | Boolean | By default, the upsert() (updateOrCreate() ) method does not enforce valid model data. Instead, it logs validation errors to the console. This preserves backwards compatibility with older 2.x versions.
Set this property to true to ensure that Set this property to false to prevent By default, |
allowEternalTokens | Boolean | Allow access tokens that never expire. |
Data source-specific options
When a model is attached a data source of certain type such as Oracle or MySQL, you can specify the name of the database schema and table as properties under the key with the name of the connector type. The value of this key must match the value of the corresponding connector
property in datasources.json. For example, in the snippet below, there would be an entry in datasources.json
like this: "myDB": { "name": "myDB", "connector": "mysql", ... }
.
... "options": { "mysql": { "table": "location" }, "mongodb": { "collection": "location" }, "oracle": { "schema": "BLACKPOOL", "table": "LOCATION" } }, ...
Properties
The properties key defines one or more properties, each of which is an object that has keys described in the following table. Below is an example a basic property definition:
... "properties": { "firstName": { "type": "String", "required": "true" }, "id": { "type": "Number", "id": true, "description": "User ID" }, ...
General property properties :
Each model property can have the properties described in the following table. Only the type
property is required; for properties with only a type
, you can use the following shorthand:
"propertyName": "type"
For example:
... "emailVerified": "boolean", "status": "string", ...
Property Options :
Key | Required | Type | Description |
---|---|---|---|
label | No | String | Default value is field name. label shows in admin dashboard |
default | No | any* | Default value for the property. The type must match that specified by type . |
description | No | String | Documentation for the property. You can split long descriptions into arrays of strings (lines) to keep line lengths manageable. For example: |
id | No | Boolean | Whether the property is a unique identifier. Default is false. See Id property below. |
index | No | Boolean | Whether the property represents a column (field) that is a database index. |
required | No | Boolean | Whether a value for the property is required. If true, then adding or updating a model instance requires a value for the property.
Default is false. |
type | Yes | String | Property type. Can be any type described in Field Types |
uiType | No | String | Choose your field ui component type described in UI Field Types |
defaultColumn | No | Boolean | Property can be default column in admin dashboard model list |
noedit | No | Boolean | Forbidden edit option to each model’s item |
hidden | No | Boolean | Hidden model from admin dashboard |
note | No | String | Show note in top of model list in admin dashboard |
Field Types :
The following table summarizes LoopBack’s data types.
Type | Description | Example |
---|---|---|
any | Any type, including array, object, Date, or GeoPoint | Any of: true , 123 , "foo" , [ "one", 2, true ] |
array | JSON array | |
See Array types below. | [ “one”, 2, true ] | |
Boolean | JSON Boolean | true |
buffer | Node.js Buffer object | new Buffer(42); |
date | JavaScript Date object | new Date(“December 17, 2003 03:24:00”); |
GeoPoint | LoopBack GeoPoint | new GeoPoint({lat: 10.32424, lng: 5.84978}); |
DateString | LoopBack DateString | "2000-01-01T00:00:00.000Z"
|
null | JSON null | null |
number | JSON number | 422 |
Object | JSON object or any type See Object types below.td> | { “firstName”: “John”, “lastName”: “Smith”, “age”: 25 } |
String | JSON string | “flashboard” |
In general, a property will have undefined
value if no explicit or default value is provided.
UI Field Types :
The following table summarizes flashboard ui component types.
Type | Description | Example & Options |
---|---|---|
String | Displayed as a input text in the Admin UI | { uiType: 'String' } |
Boolean | Displayed as a checkbox in the Admin UI | { uiType: 'Boolean' } |
Date | Displayed as a date picker in the Admin UI | Input should either be a valid Date, or a string in the format YYYY-MM-DD (can be blank unless field is required)
To default Date fields to the current time, set the Options
|
DateTime | Displayed as a date and time picker in the Admin UI | { type: 'String', type: 'Datetime'} |
Displayed as a text field in the Admin UI | { type: 'String', uiType: 'Email' } | |
Money | Displayed as a number field in the Admin UI | { type: 'String', uiType: 'Money' } |
Url | Displayed as a text field in the Admin UI. | { type: 'String', uiType: 'Url' } |
Text | Displayed as a input text in the Admin UI | { type: 'String', uiType: 'text' } |
Textarea | Displayed as a textarea field in the Admin UI | { type: 'String', uiType: 'textarea' } |
Number | Displayed as a number field in the Admin UI | { type: 'number', uiType: 'Number' } |
Password | Displayed as a password field in the Admin UI | { type: 'string', uiType: 'Password' } |
Name | Displayed as firstname lastname fields in the Admin UI | Schema The name field adds firstname and lastname String paths to the schema, as well as a full virtual getter and setter.{ type: 'Object', uiType: 'Name' } |
Code | Displayed with CodeMirror in the Admin UI. | According to codemirror options config you can add every options to the json field like below :
|
Color | Displayed as a text field with a color picker | { type: 'string', uiType: 'Color' } |
Html | Displayed as a text field or WYSIWYG Editor in the Admin UI. | According to quilljs editor options you can add every options to the json field like below:
|
GeoPoint | Displayed as a combination of fields (lat,lng) in the Admin UI | { type: 'Object', uiType: 'GeoPoint' } |
Slider | Displayed as a slider component to pick value | { type: 'Object', uiType: 'Slider' } options : max, min, step |
Select | Displayed as a select field in the Admin UI | { type: 'String or Number', uiType: 'Select', options: 'first,second,third' }
You can mix
|
Relationship | Displayed as an auto-suggest field in the Admin UI |
{"uiType": "Relationship",
key: Used to show model data key for select ui in admin dashboard. |
File | Displayed as a file upload field in the Admin UI | { type: 'Object', uiType: 'File' }
options: |
Hidden properties
A hidden property is not sent in the JSON data in the application’s HTTP response. The property value is an array of strings, and each string in the array must match a property name defined for the model.
An example of a hidden property is User.password
:
common/api/models/user.json
{ ... "properties": { ... "password": { "type": "string", "required": true }, ... }, "hidden": ["password", "verificationToken"], ... }
Protected properties
The protected
property is an array of strings, and each string in the array must match a property name defined for the model.
A protected property is not sent in HTTP response JSON data if the object is nested inside another object. For instance, suppose there is an Author object and a Book object. Book has a relation to Author, and Book is a public API. The Author model has personal information (such as social security number) which should be “protected” so anyone looking up the author of the book will not get that information.
An example configuring email
as a protected property:
common/models/User.json
{ ... "properties": { ... "email": { "type": "string", "required": true }, ... }, "protected": ["email"], ... }
More information available here.
Validation:
Specify constraints on data with validations
properties.
Key | Type | Descripion |
---|---|---|
default | Any | Default value of the property. |
required | Boolean | Whether the property is required. |
pattern | String | Regular expression pattern that a string should match |
max | Number | Maximum length for string types. |
min | Number | Minimum length for string types. |
length | Number | Maximum size of a specific type, for example for CHAR types. |
For example:
"username": { "type": "string", "description": "User account name", "min": 6, "max": 24 }
Relations
The relations
key defines relationships between models through a JSON object. Each key in this object is the name of a related model, and the value is a JSON object as described in the table below.
For example:
... "relations": { "accessTokens": { "model": "accessToken", "type": "hasMany", "foreignKey": "userId" }, "account": { "model": "account", "type": "belongsTo" }, "transactions": { "model": "transaction", "type": "hasMany" } }, ...
Key | Type | Description |
---|---|---|
foreignKey | String | Optional foreign key used to find related model instances. |
keyThrough | String | Foreign key to be used in a HasMany relation. |
model | String | Name of the related model. Required. |
type | String | Relation type. Required. See Creating model relations for more information. One of:
For hasMany, you can also specify a hasManyThrough relation by adding a “through” key:
See example below. |
through | String | Name of model creating hasManyThrough relation. See example below. |
Example of hasManyThrough:
"patient": { "model": "physician", "type": "hasMany", "through" : "appointment" }
ACLs
The value of the acls
key is an array of objects that describes the access controls for the model. Each object has the keys described in the table below.
"acls": [ { "permission": "ALLOW", "principalType": "ROLE", "principalId": "$everyone", "property": "myMethod" }, ... ]
Key | Type | Description |
---|---|---|
accessType | String | The type of access to apply. One of:
|
permission | String | Type of permission granted. Required. One of:
ALLOW - Explicitly grants access to the resource. DENY - Explicitly denies access to the resource. |
principalId | String | Principal identifier. Required. The value must be one of:
A user ID (String|number|any) An application ID (String|number|any) One of the following predefined dynamic roles: A custom role name, either:
|
principalType | String | Type of the principal. Required. One of:
APP USER ROLE |
property | String Array of Strings | Specifies a property/method/relation on a given model. It further constrains where the ACL applies. Can be:
A string, for example: An array of strings, for example: |
Methods
The methods
key defines remote methods for the model. Its value is an object with a string key for each remote method name:
- Instance method names must start with
prototype.
. - Static method names can be any legal name.
For example, the following defines a static remote method called “greet” and an instance method called “getProfile”.
... "methods": { "greet": { "accepts": [ { "arg": "msg", "type": "string", "http": { "source": "query" } } ], "returns": { "arg": "greeting", "type": "string" }, "http": { "verb": "get" } }, "prototype.getProfile": { ... // Instance remote method - options } ...
Remote method options
You specify remote method options when you register a remote method, either as an argument to the Model.remoteMethod()
method if you register it in code, or in the methods
key if you register it in JSON. Either way, it’s a JavaScript object with the same set of properties.
Important: All of the options properties are optional. However, if the remote method requires arguments, you must specify accepts
; if the remote method returns a value, you must specify returns
.
Option | Description | Example |
---|---|---|
accepts | Defines arguments that the remote method accepts that map to the static method you define. For the example above, the function signature is |
so The default value is the empty array, |
accessScopes | Defines access scopes. A user will be allowed to invoke this remote method only when their access token was granted at least one of the scopes defined by accessScopes list. See also Authorization scopes.
The default value is a list with a single scope | accessScopes: [ ‘read’, ‘read:user’ ] |
description | Text description of the method, used by API documentation generators such as Swagger. You can put long strings in an array if needed (see note below). | |
http | Specifies information about the route at which the method is exposed. See http property below. td> | |
notes | Additional notes, used by API documentation generators like Swagger. You can put long strings in an array if needed (see note below). | |
returns | Describes the remote method’s callback arguments; See Argument descriptions. The err argument is assumed; do not specify. Default if not provided is the empty array,[] . | returns: {arg: ‘greeting’, type: ‘string’} |
Tip: You can split long strings in the description
and notes
options into arrays of strings (lines) to keep line lengths manageable. For example:
[ "Lorem ipsum dolor sit amet, consectetur adipiscing elit,", "sed do eiusmod tempor incididunt ut labore et dolore", "magna aliqua." ]
Http Property
The http
property provides information on HTTP route at which the remote method is exposed.
Option | Description | Example |
---|---|---|
path | HTTP path (relative to the model) at which the method is exposed. | http: {path: ‘/sayhi’} |
verb | HTTP method (verb) at which the method is available. One of:
| |
status | Default HTTP status set when the callback is called without an error. | http: {status: 201} |
errorStatus | Default HTTP status set when the callback is called with an error. | http: {errorStatus: 400} |
Argument descriptions
The accepts
and returns
options properties define either a single argument as an object or an ordered set of arguments as an array. The following table describes the properties of each individual argument.
Property (key) | Type | Description |
---|---|---|
arg | String | Argument name |
description | String or Array | A text description of the argument. This is used by API documentation generators like Swagger. You can put long strings in an array if needed (see note above). |
http | Object or Function | For input arguments: a function or an object describing mapping from HTTP request to the argument value. See HTTP mapping of input arguments below. |
http.target | String | Map the callback argument value to the HTTP response object. The following values are supported. status sets the res.statusCode to the provided value header sets the http.header or arg named header to the value |
required | Boolean | True if argument is required; false otherwise. | root | Boolean | For callback arguments: set this property to true if your function has a single callback argument to use as the root object returned to remote caller. Otherwise the root object returned is a map (argument-name to argument-value). |
type | String | Argument datatype; must be a Loopback type. Additionally, callback arguments allow a special type “file”; see below. |
default | String | Default value that will be used to populate loopback-explorer input fields and swagger documentation. Note: This value will not be passed into remote methods function if argument is not present. |
For example, a single argument, specified as an object:
{arg: 'myArg', type: 'number'}
Multiple arguments, specified as an array:
[ {arg: 'arg1', type: 'number', required: true}, {arg: 'arg2', type: 'array'} ]