Models are a representation of the database's structure. They are split into two separate files. A JavaScript file that contains the model options (e.g: lifecycle hooks), and a JSON file that represents the data structure stored in the database.
Another type of model is named `components`. A component is a data structure that can be used in one or many other API's model. There is no lifecycle related, only a JSON file definition.
The **Content Types** models are defined in each `./api/**/models/` folder. Every JavaScript or JSON file in these folders will be loaded as a model. They are also available through the `strapi.models` and `strapi.api.**.models` global variables. Usable everywhere in the project, they contain the ORM model object that they refer to. By convention, a model's name should be written in lowercase.
If you are just starting out it is very convenient to generate some models with the Content Type Builder directly in the admin interface. You can then review the generated model mappings on the code level. The UI takes over a lot of validation tasks and gives you a feeling for available features.
Use the CLI and run the following command `strapi generate:model restaurant name:string description:text`.<br>Read the [CLI documentation](../cli/CLI.md) for more information.
In this example, the model `Restaurant` will be accessible through the `Restaurants` global variable. The data will be stored in the `Restaurants_v1` collection or table and the model will use the `mongo` connection defined in `./config/database.js`
::: warning
If not set manually in the JSON file, Strapi will adopt the filename as `globalId`.
The `globalId` serves as a reference to your model within relations and Strapi APIs. If you chose to rename it (either by renaming your file or by changing the value of the `globalId`), you'd have to migrate your tables manually and update the references.
Please note that you should not alter the Strapi's models `globalId` (plugins and core models) since they are used directly within Strapi APIs and other models' relations.
The `connection` value can be changed whenever you want, but you should be aware that there is no automatic data migration process. Also if the new connection doesn't use the same ORM you will have to rewrite your queries.
:::
## Model information
The info key on the model-json states information about the model. This information is used in the admin interface, when showing the model.
-`name`: The name of the model, as shown in admin interface.
-`description`: The description of the model.
-`icon`: The fontawesome V5 name - _only for Components_
**Path —** `Restaurant.settings.json`.
```json
{
"info": {
"name": "restaurant",
"description": ""
}
}
```
## Model options
The options key on the model-json states.
-`timestamps`: This tells the model which attributes to use for timestamps. Accepts either `boolean` or `Array` of strings where first element is create date and second element is update date. Default value when set to `true` for Bookshelf is `["created_at", "updated_at"]` and for MongoDB is `["createdAt", "updatedAt"]`.
-`privateAttributes`: This configuration allows to treat a set of attributes as private, even if they're not actually defined as attributes in the model. Accepts an `Array` of strings. It could be used to remove from API responses timestamps or `_v` when using MongoDB. The set of `privateAttributes` defined in the model are merged with the `privateAttributes` defined in the global Strapi configuration.
-`populateCreatorFields`: Configure whether the API response should include `created_by` and `updated_by` fields or not. Accepts a `boolean`. The default value is `false`.
If you're using SQL databases, you should use the native SQL constraints to apply them.
-`required` (boolean) — If true, adds a required validator for this property.
-`unique` (boolean) — Whether to define a unique index on this property.
-`index` (boolean) — Adds an index on this property, this will create a [single field index](https://docs.mongodb.com/manual/indexes/#single-field) that will run in the background. _Only supported by MongoDB._
-`max` (integer) — Checks if the value is greater than or equal to the given maximum.
-`min` (integer) — Checks if the value is less than or equal to the given minimum.
**Security validations**
To improve the Developer Experience when developing or using the administration panel, the framework enhances the attributes with these "security validations":
-`autoPopulate` (boolean) - If false, the related data will not populate within REST responses. (This will not stop querying the relational data on GraphQL)
-`options` (string) — The value is a set of options passed to [the underlying `uid` generator](https://github.com/sindresorhus/slugify). A caveat is that the resulting `uid` must abide to the following RegEx `/^[A-Za-z0-9-_.~]*$`.
user: '5c151d9d5b1d55194d3209be', // The id of the user you want to link
})
);
```
:::
::: tab "One-to-Many" id="one-to-many"
One-to-Many relationships are useful when an entry can be linked to multiple entries of another Content Type. And an entry of the other Content Type can be linked to only one entry.
articles: ['5c151d51eb28fd19457189f6', '5c151d51eb28fd19457189f8'], // Set of ALL articles linked to the user (existing articles + new article or - removed article)
})
);
```
:::
::: tab "Many-to-Many" id="many-to-many"
Many-to-Many relationships are useful when an entry can be linked to multiple entries of another Content Type. And an entry of the other Content Type can be linked to many entries.
(NoSQL databases only) The `dominant` key defines which table/collection should store the array that defines the relationship. Because there are no join tables in NoSQL, this key is required for NoSQL databases (e.g. MongoDB).
**NOTE**:
(NoSQL databases only) The `collectionName` key defines the name of the join table. It has to be specified once, in the `dominant` attribute of the relation. If it is not specified, Strapi will use a generated default one. It is useful to define the name of the join table when the name generated by Strapi is too long for the database you use.
categories: ['5c151d51eb28fd19457189f6', '5c151d51eb28fd19457189f8'], // Set of ALL categories linked to the product (existing categories + new category or - removed category).
Polymorphic relationships are the solution when you don't know which kind of model will be associated to your entry, or when you want to connect different types of models to a model.
The `filter` attribute is optional (but we highly recommend to use it every time). If it's provided it adds a new match level to retrieve the related data.
For example, the `Product` model might have two attributes which are associated to the `Image` model. To distinguish which image is attached to the `cover` field and which images are attached to the `pictures` field, we need to save and provide this to the database.
If you're using MongoDB for your database, you don't need to do anything. Everything is natively handled by Strapi. However, to implement a polymorphic relationship with SQL databases, you need to create two tables.
The first table to create is the table which has the same name as your model.
```
CREATE TABLE `image` (
`id` int(11) NOT NULL,
`name` text NOT NULL,
`text` text NOT NULL
)
```
**NOTE**:
If you've overridden the default table name given by Strapi by using the `collectionName` attribute. Use the value set in the `collectionName` to name the table.
The second table will allow us to associate one or many others entries to the `Image` model. The name of the table is the same as the previous one with the suffix `_morph`.
```
CREATE TABLE `image_morph` (
`id` int(11) NOT NULL,
`image_id` int(11) NOT NULL,
`related_id` int(11) NOT NULL,
`related_type` text NOT NULL,
`field` text NOT NULL
)
```
-`image_id` is using the name of the first table with the suffix `_id`.
- **Attempted value:** It corresponds to the id of an `Image` entry.
-`related_id` is using the attribute name where the relation happens with the suffix `_id`.
- **Attempted value:** It corresponds to the id of an `Article` or `Product` entry.
-`related_type` is using the attribute name where the relation happens with the suffix `_type`.
- **Attempted value:** It corresponds to the table name where the `Article` or `Product` entry is stored.
-`field` is using the filter property value defined in the model. If you change the filter value, you have to change the name of this column as well.
- **Attempted value:** It corresponds to the attribute of an `Article`, `Product` with which the `Image` entry is related.
| id | image_id | related_id | related_type | field |
The lifecycle hooks are functions that get triggered when the Strapi [`queries`](../concepts/queries.md) are called. They will get triggered automatically when you manage your content in the Admin Panel or when you develop custom code using `queries`·
To configure a `ContentType` lifecycle hooks you can set a `lifecycles` key in the `{modelName}.js` file located at `./api/{apiName}/models/{modelName}.js` folder.
You can mutate one of the parameters to change its properties. Make sure not to reassign the parameter as it will have no effect:
**This will Work**
```js
module.exports = {
lifecycles: {
beforeCreate(data) {
data.name = 'Some fixed name';
},
},
};
```
**This will NOT Work**
```js
module.exports = {
lifecycles: {
beforeCreate(data) {
data = {
...data,
name: 'Some fixed name',
};
},
},
};
```
:::
### Custom use
When you are building custom ORM specific queries the lifecycles will not be triggered. You can however call a lifecycle function directly if you wish.