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 a Value 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 an Entity becauseeach customer has a unique customer id. Two instances of Customer with thesame customer id are equal since they refer to the same customer. For example:
  1. {
  2. "name": "Customer",
  3. "properties": {
  4. "id": "string",
  5. "lastName": "string",
  6. "firstName": "string",
  7. "email": "string",
  8. "address": "Address"
  9. }
  10. }

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.

  1. export class Customer {
  2. email: string;
  3. isMember: boolean;
  4. cart: ShoppingCart;
  5. }

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/repositorymodule.

  1. import {model, property} from '@loopback/repository';
  2. @model()
  3. export class Customer {
  4. @property()
  5. email: string;
  6. @property()
  7. isMember: boolean;
  8. @property()
  9. cart: ShoppingCart;
  10. }

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.

  1. import {model, property, Entity} from '@loopback/repository';
  2. @model()
  3. export class Product extends Entity {
  4. @property({
  5. id: true,
  6. description: 'The unique identifier for a product',
  7. })
  8. id: number;
  9. name: string;
  10. @property()
  11. slug: string;
  12. constructor(data?: Partial<Product>) {
  13. super(data);
  14. }
  15. }

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:

  1. @model({
  2. name: 'Category',
  3. settings: {
  4. // etc...
  5. },
  6. // define properties by @property decorator below
  7. })
  8. class Category extends Entity {
  9. // etc...
  10. @property({type: 'number'})
  11. }

The model decorator already knows the name of your model class, so you can omitit.

  1. @model()
  2. class Product extends Entity {
  3. name: string;
  4. // other properties...
  5. }

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).
  • optionsin lb3 doesn’t have the mapping feature in LB4 yet. (see forfurther discussion.)As for entries in settings, 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:

  1. @model({
  2. settings: {
  3. hiddenProperties: ['password']
  4. }
  5. })
  6. class MyUserModel extends Entity {
  7. @property({id: true})
  8. id: number;
  9. @property({type: 'string'})
  10. email: string;
  11. @property({type: 'string'})
  12. password: string;
  13. ...
  14. }

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:

  1. @model()
  2. class Product extends Entity {
  3. @property({
  4. name: 'name',
  5. type: 'string',
  6. // Specify the JSON validation rules here
  7. maxLength: 30,
  8. minLength: 10,
  9. },
  10. })
  11. public name: string;
  12. }

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.

  1. @model()
  2. class Product extends Entity {
  3. @property()
  4. public name: string; // The type information for this property is String.
  5. }

For consistency, we require the use of the @property.array decorator, whichadds the appropriate metadata for type inference of your array properties.

  1. @model()
  2. class Order extends Entity {
  3. @property.array(Product)
  4. items: Product[];
  5. }
  6. @model()
  7. class Thread extends Entity {
  8. // Note that we still require it, even for primitive types!
  9. @property.array(String)
  10. posts: string[];
  11. }

Additionally, the @property.array decorator can still take an optional secondparameter to define or override metadata in the same fashion as the @propertydecorator.

  1. @model()
  2. class Customer extends Entity {
  3. @property.array(String, {
  4. name: 'names',
  5. required: true,
  6. })
  7. aliases: string[];
  8. }

Use the @loopback/repository-json-schema module to build a JSON schema from adecorated model. Type information is inferred from the @model and @propertydecorators. 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:

  1. {
  2. "title": "Product",
  3. "properties": {
  4. "name": {
  5. "type": "string"
  6. },
  7. "type": {
  8. "$ref": "#/definitions/Category"
  9. }
  10. },
  11. "definitions": {
  12. "Category": {
  13. "properties": {
  14. "name": {
  15. "type": "string"
  16. }
  17. }
  18. }
  19. },
  20. }

If a custom type is specified for a decorated property in a model definition,then a reference$reffield 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.