Note:Models describe the shape of data. Behavior like CRUD operations is added by repositories. This is different from LoopBack 3.x where models implement behavior too.
Tip: A single model can be used with multiple different Repositories.
Models can be used for data exchange on the wire or between different systems.For example, a JSON object conforming to the Customer
model definition can bepassed in REST/HTTP payload to create a new customer or stored in a documentdatabase such as MongoDB. Model definitions can also be mapped to other forms,such as relational database schemas, XML schemas, JSON schemas, OpenAPI schemas,or gRPC message definitions, and vice versa.
There are two subtly different types of models for domain objects:
- Value Object: A domain object that does not have an identity (ID). Itsequality is based on the structural value. For example,
Address
can bemodeled as aValue Object
because two US addresses are equal if they havethe same street number, street name, city, and zip code values. For example:
- Entity: A domain object that has an identity (ID). Its equality is based onthe identity. For example,
Customer
can be modeled as anEntity
becauseeach customer has a unique customer id. Two instances ofCustomer
with thesame customer id are equal since they refer to the same customer. For example:
{
"name": "Customer",
"properties": {
"id": "string",
"lastName": "string",
"firstName": "string",
"email": "string",
"address": "Address"
}
}
Currently, we provide the @loopback/repository
module, which provides specialdecorators for adding metadata to your TypeScript/JavaScript classes in order touse them with the legacy implementation of the.
At its core, a model in LoopBack is a simple JavaScript class.
export class Customer {
email: string;
isMember: boolean;
cart: ShoppingCart;
}
Extensibility is a core feature of LoopBack. There are external packages thatadd additional features, for example, integration with the juggler bridge orJSON Schema generation. These features become available to a LoopBack modelthrough the @model
and @property
decorators from the @loopback/repository
module.
import {model, property} from '@loopback/repository';
@model()
export class Customer {
@property()
email: string;
@property()
isMember: boolean;
@property()
cart: ShoppingCart;
}
LoopBack can automatically create model definitions by discovering the schema ofyour database. See Discovering models for more detailsand a list of connectors supporting model discovery.
To define a model for use with the juggler bridge, extend your classes fromEntity
and decorate them with the @model
and @property
decorators.
import {model, property, Entity} from '@loopback/repository';
@model()
export class Product extends Entity {
@property({
id: true,
description: 'The unique identifier for a product',
})
id: number;
name: string;
@property()
slug: string;
constructor(data?: Partial<Product>) {
super(data);
}
}
Models are defined primarily by their TypeScript class. By default, classesforbid additional properties that are not specified in the type definition. Thepersistence layer respects this constraint and configures underlyingPersistedModel classes to enforce strict
mode.
The model decorator can be used without any additional parameters, or can bepassed in a ModelDefinitionSyntax:
@model({
name: 'Category',
settings: {
// etc...
},
// define properties by @property decorator below
})
class Category extends Entity {
// etc...
@property({type: 'number'})
}
The model decorator already knows the name of your model class, so you can omitit.
@model()
class Product extends Entity {
name: string;
// other properties...
}
However, the model decorator in LoopBack 4 is not exactly the same as what it isin LoopBack 3. For example, in we canpass in a model definition syntax in the model decorator, such as properties,options, relation etc. But not all these entries are available in lb4 modeldecorator:NOTICE: in LoopBack 4 we only support settings
in the ModelDefinitionSyntaxfor now. Those top-level properties
in lb3 now are passed in settings
.
properties
now are defined in@property
decorator (see below for moreinformation).options
in lb3 doesn’t have the mapping feature in LB4 yet. (see forfurther discussion.)As for entries insettings
, LoopBack 4 supports these built-in entries fornow:
Supported Entries of Settings
Unsupported Entries of Settings
To discover more about Model Decorator
in LoopBack 4, please checklegacy-juggler-bridge fileand.
Hidden properties
The properties are stored in the database, available in JS/TS code, can be setvia POST/PUT/PATCH requests, but they are removed from response bodies(.toJSON()
output).
To hide a property, you can use the hiddenProperties
setting like this:
@model({
settings: {
hiddenProperties: ['password']
}
})
class MyUserModel extends Entity {
@property({id: true})
id: number;
@property({type: 'string'})
email: string;
@property({type: 'string'})
password: string;
...
}
The property decorator takes in the same arguments used in LoopBack 3 forindividual property entries:
The complete list of valid attributes for property definitions can be found inLoopBack 3’s.
You can also specify the validation rules in the field jsonSchema
. Forexample:
@model()
class Product extends Entity {
@property({
name: 'name',
type: 'string',
// Specify the JSON validation rules here
maxLength: 30,
minLength: 10,
},
})
public name: string;
}
Check out the documentation ofParsing requests to see how to do it indetails.The property decorator leverages LoopBack’sto determine the type of a particular property.
@model()
class Product extends Entity {
@property()
public name: string; // The type information for this property is String.
}
For consistency, we require the use of the @property.array
decorator, whichadds the appropriate metadata for type inference of your array properties.
@model()
class Order extends Entity {
@property.array(Product)
items: Product[];
}
@model()
class Thread extends Entity {
// Note that we still require it, even for primitive types!
@property.array(String)
posts: string[];
}
Additionally, the @property.array
decorator can still take an optional secondparameter to define or override metadata in the same fashion as the @property
decorator.
@model()
class Customer extends Entity {
@property.array(String, {
name: 'names',
required: true,
})
aliases: string[];
}
Use the @loopback/repository-json-schema module
to build a JSON schema from adecorated model. Type information is inferred from the @model
and @property
decorators. The @loopback/repository-json-schema
module contains thegetJsonSchema
function to access the metadata stored by the decorators tobuild a matching JSON schema of your model.
jsonSchema
from above would return:
{
"title": "Product",
"properties": {
"name": {
"type": "string"
},
"type": {
"$ref": "#/definitions/Category"
}
},
"definitions": {
"Category": {
"properties": {
"name": {
"type": "string"
}
}
}
},
}
If a custom type is specified for a decorated property in a model definition,then a reference$ref
field is created for it and a definitions
sub-schema is created at thetop-level of the schema. The definitions
sub-schema is populated with the typedefinition by recursively calling getJsonSchema
to build its properties. Thisallows for complex and nested custom type definition building. The example aboveillustrates this point by having the custom type Category
as a property of ourProduct
model definition.
Supported JSON keywords
Note:
This feature is still a work in progress and is incomplete.
Following are the supported keywords that can be explicitly passed into thedecorators to better tailor towards the JSON Schema being produced:
You might decide to use an alternative ORM/ODM in your LoopBack application.LoopBack 4 no longer expects you to provide your data in its own custom Modelformat for routing purposes, which means you are free to alter your classes tosuit these ORMs/ODMs.
However, this also means that the provided schema decorators will serve nopurpose for these ORMs/ODMs. Some of these frameworks may also providedecorators with conflicting names (e.g. another @model
decorator), which mightwarrant avoiding the provided juggler decorators.