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:

  1. With the command-line tool, by using the LoopBack model generator.
  2. From an existing relational database, by using model discovery.
  3. 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

  1. 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.

  1. 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.

{
  "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. Use Model 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 files foo-bar.json and foo-bar.js in common/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:
  • true: id property is added to the model automatically. This is the default.
  • false: id property is not added to the model

See ID properties for more information. The idInjection property in options (if present) takes precedence.

options Object N/A JSON object that specifies model options. See Options below.

plural String Plural of nameproperty Plural form of the model name.

properties Object N/A JSON object that specifies the properties in the model. See Properties below.

forceId Booleantrue 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 Booleanfalse If true, in HTTP paths, converts:

  • Uppercase letters to lowercase.
  • Underscores (_) to dashes (-).
  • CamelCase to dash-delimited.

Does not affect placeholders (for example “:id”). For example, “MyClass” or “My_class” becomes “my-class”.

strict Booleanfalse.
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:

  • true: Only properties defined in the model are accepted. Use if you want to ensure the model accepts only predefined properties. If you try to save a model instance with properties that are not predefined, LoopBack throws a ValidationError.
  • false: The model is an open model and accepts all properties, including ones not predefined in the model. This mode is useful to store free-form JSON data to a schema-less database such as MongoDB.
  • "filter": Only properties defined in the model are accepted. If you load or save a model instance with properties that are not predefined, LoopBack will ignore them. This is particularly useful when dealing with old data that you wish to lose without a migration script.

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 upsert() returns an error when validation fails. The next major version of LoopBack will enable this option (set as true) by default.

Set this property to false to prevent upsert() from calling any validators at all.

By default, upsert() calls all validators and reports any validation errors to the console log.

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
defaultColumnNo BooleanProperty can be default column in admin dashboard model list
noedit No BooleanForbidden edit option to each model’s item
hidden No BooleanHidden 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"

"2000-01-01"
"2000-01-01 12:00:00"

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 default option to Date.now

Options
format string - the default format pattern to use, defaults to Do MMM YYYY

{ type: 'Date', ,uiType: 'Date', options: { format:'DD-MM-YY' } }

DateTimeDisplayed as a date and time picker in the Admin UI { type: 'String', type: 'Datetime'}
Email 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' }
TextareaDisplayed 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' }
PasswordDisplayed as a password field in the Admin UI { type: 'string', uiType: 'Password' }
Name Displayed as firstname lastname fields in the Admin UISchema
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 :

{ type: 'String', uiType: 'Code', options: { mode: 'javascript', lineNumbers: true }

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:

{ type: 'String', uiType: 'Html', options: { placeholder: 'Some text...', 'theme': 'snow' } }

GeoPointDisplayed 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 String and Object items in the options Array:

{ type: 'String or Number', uiType: 'Select', options: ['first', 'second', { value: 'third', label: 'The third one' }] }

Relationship Displayed as an auto-suggest field in the Admin UI
{"uiType": "Relationship",
"options": {
"ref": "Users",
"filter": { "type": "user" },
"key": "email"
}

key: Used to show model data key for select ui in admin dashboard.
ref: Specify the related Model using the ref option
filter: You can filter a relationship field using the filters option.

File Displayed as a file upload field in the Admin UI { type: 'Object', uiType: 'File' }

options:
dest: String - required, the path to store uploaded file
allowedTypes Array of String - optional white-list of allowed mime types for uploaded file
multiple: Boolean - optional, default false, multiple upload files option
maxSize: Number - optional, default max size upload file is loopback container storage default maxSize

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:
  • hasMany
  • belongsTo
  • hasAndBelongsToMany

For hasMany, you can also specify a hasManyThrough relation by adding a “through” key:

{through: 'modelName'}

See example below.

through StringName 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:
  • READ

  • WRITE

  • EXECUTE

    • (default)
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:
    $everyone - Everyone
    $owner - Owner of the object
    $authenticated - Authenticated user
    $unauthenticated - Unauthenticated user

  • A custom role name, either:

    • static, directly mapped to a principal
    • dynamic, registered with a custom role resolver
  • principalTypeString 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: "create"

  • An array of strings, for example: ["create", "update"]



  • 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
    Person.greet(name, age, callback)...
    

    so name is the first argument, age is the second argument and callback is automatically provided by LoopBack (do not specify it in your accepts array). For more information, see Argument descriptions.

    The default value is the empty array, [ ]. | { … accepts: [
    {arg: ‘name’, type: ‘string’},
    {arg: ‘age’, type: ‘number’},
    …],
    … }

    accessScopesDefines 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 DEFAULT.

    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:
    • get
    • post (default)
    • patch
    • put
    • del
    • all | http: {path: ‘/sayhi’,
      verb: ‘get’}
    status Default HTTP status set when the callback is called without an error. http: {status: 201}
    errorStatusDefault 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
    requiredBoolean 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'}
    ]