Chinese Documentation : Model definition JSON file

Overview

The LoopBack Model generator creates model JSON files in the /common/models directory named model-name.json, where model-name is the model name of each model; for example, customer.json.   The model JSON file defines models, relations between models, and access to models. 

Here is an excerpt from an example model definition file for a customer model that would be in /common/models/customer.json:

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
  "validations": [...],  // See Validations below
  "relations": {...},  // See Relations below
  "acls": [...],  // See ACLs below
  "scopes": {...},  // See Scopes below
  "indexes" : { ...}, // See Indexes below
  "methods": [...],  // See Methods below - New for LB2.0 - Remoting metadata
  "http": {"path": "/foo/mypath"}
}

Top-level properties

Properties are required unless otherwise designated.

PropertyTypeDescription
nameStringName of the model.
descriptionString or Array

Optional description of the model.

You can split long descriptions into arrays of strings (lines) to keep line lengths manageable.

[
"Lorem ipsum dolor sit amet, consectetur adipiscing elit,"
"sed do eiusmod tempor incididunt ut labore et dolore",
"magna aliqua."
pluralString

Plural form of the model name.

Optional: Defaults to plural of name property using standard English conventions.

baseString

Name of another model that this model extends. The model will "inherit" properties and methods of the base model.

idInjectionBoolean

Whether to automatically add an id property to the model:

  • trueid property is added to the model automatically. This is the default.
  • falseid property is not added to the model

See ID properties for more information.

Optional; default is true. If present, the idInjection propery in options takes precedence.

http.pathStringCustomized HTTP path for REST endpoints of this model.
strictBoolean

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.
  • 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.
  • "throw": Throws an exception if properties not defined for the model are used in an operation.
  • Undefined: Defaults to false unless the data source is backed by a relational database such as Oracle or MySQL.

options

Object

JSON object that specifies model options. See Options below.

propertiesObject

JSON object that specifies the properties in the model. See Properties below.

relationsObject

Object containing relation names and relation definitions.

See Relations below.

aclsArray

Set of ACL specifications that describes access control for the model.

See Acls below.

Options

REVIEW COMMENT from Rand
What can we say about these properties? Are they all specific to data sources? Are there any common properties? Can we describe properties valid for each connector?

The options key specifies 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. 

  ...
  "options": {
    "mysql": {
      "table": "location"
    },
    "mongodb": {
      "collection": "location"
    },
    "oracle": {
      "schema": "BLACKPOOL",
      "table": "LOCATION"
    }
  },
  ...
Icon

You can set idInjection here in options or at the top-level. The value set here takes precedence over the top-level value of idInjection.

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, 
    "doc": "User ID"
},
...

General property properties

KeyRequired?TypeDescription
defaultNoAny*Default value for the property. The type must match that specified by type.
descriptionNoString or Array

Documentation for the property.

You can split long descriptions into arrays of strings (lines) to keep line lengths manageable.

[
"Lorem ipsum dolor sit amet, consectetur adipiscing elit,"
"sed do eiusmod tempor incididunt ut labore et dolore",
"magna aliqua."
 
docNoStringDocumentation for the property. Deprecated, use "description" instead.
idNoBoolean

Whether the property is a unique identifier. Default is false.

See Id property below.

requiredNoBoolean

Whether a value for the property is required.

Default is false.

type

Yes

String

Property type. Can be any type described in LoopBack types.

*NoAnySee below.

ID properties

A model representing data to be persisted in a database usually has one or more ID properties that uniquely identify the model instance. For example, the user model might have user IDs.

By default, if no ID properties are defined and the idInjection property is true (or is not set, since true is the default), LoopBack automatically adds an id property to the model as follows:

 id: {type: Number, generated: true, id: true}

The generated property indicates the ID will be automatically generated by the database. If true, the connector decides what type to use for the auto-generated key. For relational databases, such as Oracle or MySQL, it defaults to number. If your application generates unique IDs, set it to false.

To explicitly specify a property as ID, set the id property of the option to true. The id property value must be one of:

  • true: the property is an ID.

  • false (or any value that converts to false): the property is not an ID (default).

  • Positive number, such as 1 or 2: the property is the index of a composite ID.

In database terms, key column(s) are ID properties. Such properties are defined with the 'id' attribute set to true or a number as the position for a composite key. For example,

{
  "myId": {
    "type": "string", 
    "id": true 
   }
}

Then:

  1. If a model doesn't have explicitly-defined ID properties, LoopBack automatically injects a property named "id" unless the idInjection option is set to false.

  2. If an ID property has generated set to true, the connector decides what type to use for the auto-generated key. For example for SQL Server, it defaults to number.

  3. LoopBack CRUD methods expect the model to have an "id" property if the model is backed by a database.

  4. A model without any "id" properties can only be used without attaching to a database.

Composite IDs

LoopBack supports the definition of a composite ID that has more than one property. For example:

var InventoryDefinition = { 
  productId: {type: String, id: 1}, 
  locationId: {type: String, id: 2}, 
  qty: Number 
}

The composite ID is (productId, locationId) for an inventory model.

Icon

Composite IDs are not currently supported as query parameters in REST APIs.

Data mapping properties

When using a relational database data source, you can specify the following properties that describe the columns in the database.  

PropertyTypeDescription
columnNameStringColumn name
dataTypeStringData type as defined in the database
dataLengthNumberData length
dataPrecisionNumberNumeric data precision
dataScaleNumberNumeric data scale
nullableBooleanIf true, data can be null

For example, to map a property to a column in an Oracle database table, use the following:

...
"name": {
      "type": "String",
      "required": false,
      "length": 40,
      "oracle": {
        "columnName": "NAME",
        "dataType": "VARCHAR2",
        "dataLength": 40,
        "nullable": "Y"
      }
    }
...

Conversion and formatting properties

Format conversions are declared in properties, as described in the following table:

KeyTypeDescription
trimBooleanWhether to trim the string
lowercaseBooleanWhether to convert a string to lowercase
uppercaseBooleanWhether to convert a string to uppercase
formatRegular expressionFormat for a date property.

Validations

Icon

This is not yet implemented. You must currently validate in code; see Validating model data.

Specify constraints on data with validations properties.  See also Validatable class.

KeyTypeDescription
defaultAnyDefault value of the property.
requiredBooleanWhether the property is required.
patternStringRegular expression pattern that a string should match
max

Number

Maximum length for string types.
minNumberMinimum length for string types. 
lengthNumberMaximum size of a specific type, for example for CHAR types.

For example:

"username": {
  "type": "string", 
  "doc": “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"
        }
      }, 
...

 

KeyTypeDescription

model

String

Name of the related model. Required.

typeString

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.

foreignKeyStringOptional foreign key used to find related model instances.
throughStringName 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"
    }, 
    ...
]
KeyTypeDescription
accessTypeString

The type of access to apply. One of:

  • READ
  • WRITE
  • EXECUTE
  • ALL (default)

permission

String

 

Type of permission granted. Required.

One of:

  • ALARM - Generate an alarm, in a system dependent way, the access specified in the permissions component of the ACL entry.
  • ALLOW - Explicitly grants access to the resource.
  • AUDIT - Log, in a system dependent way, the access specified in the permissions component of the ACL entry.
  • DENY - Explicitly denies access to the resource.
principalIdString

Principal identifier. Required.

The value must be one of:

  • A user ID (String|number|any)
  • One of the following predefined dynamic roles:
    • $everyone - Everyone
    • $owner - Owner of the object
    • $related - Any user with a relationship to the object
    • $authenticated - Authenticated user
    • $unauthenticated - Unauthenticated user
  • A static role name
Icon

$related principalId is not yet implemented.

principalTypeString

Type of the principal. Required.

One of:

  • Application
  • User
  • Role
property Specifies a property/method/relation on a given model. It further constrains where the ACL applies.

Scopes

Scopes enable you to specify commonly-used queries that you can reference as method calls on a model.

The scopes key defines one or more scopes (named queries) for models. A scope maps a name to a predefined filter object to be used by the model's find() method; for example:

"scopes": {
	"vips": {"where": {"vip": true}}, 
	"top5": {"limit": 5, "order": "age"}
}

The snippet above defines two named queries for the model:

  • vips: Find all model instances with vip flag set to true
  • top5: Find top five model instances ordered by age

Within the scopes object, the keys are the names, and each value defines a filter object for Model.find().

You can also define a scope programmatically using a model's scope() method, for example:

User.scope('vips', {where: {vip: true});
User.scope('top5': {limit: 5, order: 'age'});

Now you can call the methods defined by the scopes; for example:

User.vips(function(err, vips) {
...
}); 

Default scope

If you wish for a scope to be applied across all queries to the model, you can use the default scope for the model itself.

For example:

{
  "name": "Product",
  "properties": {
    ...
  }
  "scope": {
    "order": "name",
    "limit": 100
    "where": {
      "deleted": false
    }
  }
}

Now, any CRUD operation with a query parameter runs in the default scope will be applied; for example, assuming the above scope, a find opearation such as

Product.find({offset: 0}, cb);

Becomes the equivalent of this:

Product.find({order: "name", offset: 0, limit: 100, where: {deleted: false}}, cb)

Methods

You can declare remote methods here.  Until this feature is implemented, you must declare remote methods in code; see 远程方法(Remote methods).

Icon

This feature is not yet implemented.

Indexes

Declare indexes for a model with the indexes property, for example:

"indexes": {
  "name_age_index": {
    "keys": {"name": 1, "age": -1}
  }, 
  "age_index": {"age": -1}
}

The snippet above creates two indexes for the declaring model:

  • A composite index named name_age_index with two keys: name in ascending order and age in descending order.
  • A simple index named age_index with one key: age in descending order.

The full syntax for an individual index is:

"<indexName>": {
  "keys": {
     "<key1>": 1,
     "<key2>": -1
   },
   "options": {
     "unique": true
   }
}
Icon

A key value of 1 specifies ascending order, and -1 specifies descending order.

If you don't need to specify any options, you can use a shortened form:

"<indexName>": {
  "<key1>": 1,
  "<key2>": -1
}  

You can specify indexes at the model property level too, for example:

{
  "name": { "type": "String", "index": true },
  "email": { "type": "String", "index": {"unique": true} },
  "age": "Number"
}

This example creates two indexes: one for the name key and another one for the email key. The email index is unique.