Relationships
Please be sure of your agent type and version and pick the right documentation accordingly.
This is the documentation of the forest-express-sequelize and forest-express-mongoose Node.js agents that will soon reach end-of-support.
forest-express-sequelize v9 and forest-express-mongoose v9 are replaced by @forestadmin/agent v1.
Please check your agent type and version and read on or switch to the right documentation.
This is still the latest Ruby on Rails documentation of the forest_liana agent, you’re at the right place, please read on.
This is the documentation of the django-forestadmin Django agent that will soon reach end-of-support.
If you’re using a Django agent, notice that django-forestadmin v1 is replaced by forestadmin-agent-django v1.
If you’re using a Flask agent, go to the forestadmin-agent-flask v1 documentation.
Please check your agent type and version and read on or switch to the right documentation.
This is the documentation of the forestadmin/laravel-forestadmin Laravel agent that will soon reach end-of-support.
If you’re using a Laravel agent, notice that forestadmin/laravel-forestadmin v1 is replaced by forestadmin/laravel-forestadmin v3.
If you’re using a Symfony agent, go to the forestadmin/symfony-forestadmin v1 documentation.
Please check your agent type and version and read on or switch to the right documentation.
Relationships
What is a relationship?
A relationship is a connection between two collections.
Relationships are visible and actionable in Forest Admin:
hasMany(1)belongsToorhasOne(2)

If you installed Forest Admin within a Rails app, then all the relationships defined in your ActiveRecord models are supported out of the box. Check the official Rails documentation to create new ones.
If you installed Forest Admin directly on a database, then most relationships should have been automatically generated. However, depending on your database nature and structure, you may have to add some manually.
Adding relationships (databases only)
Depending on your database type, your models will have been generated in Sequelize (for SQL databases) or Mongoose (for Mongo databases).
Below are some simple snippets showing you how to add relationships. However, should you want to dig deeper, please refer to the appropriate framework's documentations:
Sequelize's documentation on adding relationships in your models (SQL)
Mongoose's documentation on adding relationships in your models (Mongodb)
Adding a hasMany relationship
hasMany relationshipIn our Live demo, a customer can have multiple orders. In that case, we have to use a hasMany relationship.
module.exports = (sequelize, DataTypes) => {
const Customer = sequelize.define('customers',
...
);
Customer.associate = (models) => {
Customer.hasMany(models.orders);
};
return Customer;
};module.exports = (mongoose, Mongoose) => {
const schema = Mongoose.Schema({
...
'orders': [{ type: Mongoose.Schema.Types.ObjectId, ref: 'orders' }],
...
}, {
timestamps: true,
});
return mongoose.model('customers', schema, 'customers');
};Note that for orders to be displayed within the related data section of your customer, they have to be populated in your database. For instance:


Adding a hasOne relationship
hasOne relationshipIn case of a one-to-one relationship between 2 collections, the opposite of a belongsTo relationship is a hasOne relationship. Taking the same example as before, the opposite of "an address belongsTo a customer" is simply "a customerhasOne address".
module.exports = (sequelize, DataTypes) => {
const Customer = sequelize.define('customers',
...
);
Customer.associate = (models) => {
Customer.hasOne(models.addresses);
};
return Customer;
};module.exports = (mongoose, Mongoose) => {
const schema = Mongoose.Schema({
...
'address': { type: Mongoose.Schema.Types.ObjectId, ref: 'addresses' },
...
}, {
timestamps: true,
});
return mongoose.model('customers', schema, 'customers');
};
Adding a belongsTo relationship
belongsTo relationshipOn our Live Demo example, the Address model has a foreignKey customer_id that points to the Customer. In other words, an addressbelongsTo a customer.
module.exports = (sequelize, DataTypes) => {
const Address = sequelize.define('addresses',
...
);
Address.associate = (models) => {
Address.belongsTo(models.customers);
};
return Address;
};module.exports = (mongoose, Mongoose) => {
const schema = Mongoose.Schema({
...
'customer_id': { type: Mongoose.Schema.Types.ObjectId, ref: 'customers' },
...
}, {
timestamps: true,
});
return mongoose.model('addresses', schema, 'addresses');
};This will work if your foreign keys are correctly named:
For a collection collectionName, the foreign key should be collection_name_id.
If this is not the case, check out the section below.

Declaring a foreign key (SQL only)
It's possible that your tables are linked in an unusual way (using names instead of ids for instance).
In that case, adding the above code will not suffice to add the belongsTo relationship. Even though we recommend you modify your database structure to stay within foreign key conventions (pointing to an id), there is a way to specify how your tables are linked.
If the field fk_customername of a table Address points to the field name of a table Customer, add the following:
...
Address.associate = (models) => {
Address.belongsTo(models.customers, {
foreignKey: 'fk_companyname'
targetKey: 'name'
});
};
...Adding a belongsToMany relationship (SQL only)
belongsToMany relationship (SQL only)belongsToMany association is often used to set up a many-to-many relationship with another model. For this example, we will consider the models Projects and Users. A user can be part of many projects, and one project has many users. The junction table that will keep track of the associations will be called userProjects, which will contain the foreign keys projectId and userId.
...
UserProjects.associate = (models) => {
UserProjects.belongsTo(models.projects, {
foreignKey: {
name: 'projectIdKey',
field: 'projectId',
},
as: 'project',
});
UserProjects.belongsTo(models.users, {
foreignKey: {
name: 'userIdKey',
field: 'userId',
},
as: 'user',
});
};
......
Users.associate = (models) => {
Users.belongsToMany(models.projects, {
through: 'userProjects',
foreignKey: 'userId',
otherKey: 'projectId',
});
};
......
Projects.associate = (models) => {
Projects.belongsToMany(models.users, {
through: 'userProjects',
foreignKey: 'projectId',
otherKey: 'userId',
});
};
...
Relationship generation rules
Forest Admin automatically generates most relationships, according to the below rules:
BelongsTo
Detecting belongsTo is straight forward, we check if the referenced table of the foreign key is unique (unique constraint or primary key), then a belongsTo association can be set between the two tables.
HasMany
If the foreign key doesn't have a uniqueness constraint, then we can define a hasMany association.
HasOne
If the foreign key also have a unique constraint or is used as the primary key of its table, then we can define a hasOne association.
BelongsToMany
We detect Many-to-Many relationships when we detect a simple junction table. We are able to detect a junction table when it contains 2 foreign keys. It can optionally contain additional fields like a primary key and technical timestamps.
BelongsTo
When a document contains an ObjectID referring to another document, we create a belongsTo relationship to the corresponding collection.
HasMany
When a document contains an array of ObjectIDs referring to other documents, we create a hasMany relationship to the corresponding collection.
HasOne
Not automatically generated.
BelongsToMany
Not automatically generated.
Last updated
Was this helpful?