Developer Guide
Other documentationsDemoCommunityGitHub
  • Forest Admin
  • Getting Started
    • Quick start
    • Development workflow
  • Reference Guide
    • How it works
      • Environments
      • Developing on Forest Admin
        • Using branches
        • Deploying your changes
        • Forest CLI commands
          • init
          • login
          • branch
          • switch
          • set-origin
          • push
          • environments:reset
          • environments:create
          • deploy
          • schema:diff [beta]
        • Express packages
    • Models
      • Enrich your models
      • Relationships
        • Create a Smart relationship
          • GetIdsFromRequest
        • Smart Relationship Examples
          • Smart hasMany relationship in mongoDB
    • Actions
      • Create and manage Smart Actions
        • Use a Smart Action Form
        • Use a Smart Action Intent
      • Smart Action Examples
        • Calculate the distance between two string addresses
        • Impersonate a user
        • Create a record with a multiselect through a many-to-many relationship
        • Handle enums with alias labels in a smart action
        • Dropdown with list of values in smart action form
        • Custom dynamic dropdown in a form using smart collections
        • Refresh hasMany relationship in smart action
        • Smart segment to restrict access to an action on a record details view
        • BelongsToMany edition through smart collection
        • Upload files to amazon s3
        • Upload several files with the File Picker
        • Retrieve smart field info in a smart action
        • Smart action to create several records from the input of a single smart action form
        • Add many existing records at the same time (hasMany-belongsTo relationship)
        • Call a webhook with record ids
        • Bulk update records
    • Smart Fields
      • Smart Field Examples
        • Add an HTML credit card as a smart field in a summary view
        • Display field with complex info in html format (rich text editor)
        • Generate signed urls to display S3 files in a smart field
        • Print a status object in a single line field
        • Sort by smart field
        • Sort by smart field that includes value from a belongsTo relationship
        • Add fields destined to the create form
        • Add validation to a smart field edition
        • Display smart field as progress bar using rich text editor
        • Update point geometry field using a smart field and algolia api
    • Smart Collections
      • Examples
        • Create a Smart Collection with Amazon S3
        • Smart relationship between model and stripe cards
        • Create records from a Smart collection
        • Searchable smart collection with records fetched from hubspot API
      • Serializing your records
    • Routes
      • Default routes
      • Extend a route
      • Override a route
    • Integrations
      • Stripe
      • Mixpanel
      • Intercom
      • Elasticsearch
        • Interact with your Elasticsearch data
        • Elasticsearch service/utils
        • Another example
      • Zendesk
        • Authentication, Filtering & Sorting
        • Display Zendesk tickets
        • Display Zendesk users
        • View tickets related to a user
        • Bonus: Direct link to Zendesk + change priority of a ticket
      • Dwolla
        • Display Dwolla customers
        • Display Dwolla funding sources
        • Display Dwolla transfers
        • Link users and Dwolla customers
        • Dwolla Service
      • Razorpay
      • Hubspot
        • Create a Hubspot company
        • Display Hubspot companies
      • Twilio
        • Send an SMS with Twilio and Zapier
      • Azure Table Storage
      • Slack
        • Send Smart Action notifications to Slack
      • Algolia
        • Geocode an address with Algolia
    • Smart Views
      • Create a Map view
      • Create a Calendar view
      • Create a Shipping view
      • Create a Gallery view
      • Create a custom tinder-like validation view
      • Create a dynamic calendar view for an event-booking use case
      • Create a custom moderation view
    • Smart Segments
    • Scopes
      • Create a scope more than one level away based on a Smart field
      • Scope on a smart field extracting a json's column attribute
    • Performance
    • Charts
      • Create an API-based Chart
      • Create a Smart Chart
      • Create Charts with AWS Redshift
  • Extra help
    • Setup
      • Install
      • Connecting Forest Admin to Your Database (Forest Cloud)
      • Forest Admin IP white-listing (Forest Cloud)
      • Why HTTPS is necessary even locally
      • Troubleshooting
      • Prevent permission errors at installation
      • Deploy your admin backend to AWS
      • Deploy your admin backend on Heroku
      • Deploy your admin backend to Ubuntu server
      • Deploy your admin backend to Google Cloud Platform
      • Install Forest Admin on a remote machine
      • Use Forest Admin with a read-only database
      • Configuring CORS headers
      • Running Forest Admin on multiple servers
      • Flatten nested fields (MongoDB)
    • Upgrade
      • Upgrade notes (Rails)
        • Upgrade to v9
        • Upgrade to v8
        • Upgrade to v7
        • Upgrade to v6
        • Upgrade to v5
        • Upgrade to v4
        • Upgrade to v3
      • Upgrade notes (SQL, Mongodb)
        • Upgrade to v9
        • Upgrade to v8
        • Upgrade to v7
        • Upgrade to v6
        • Upgrade to v5
        • Upgrade to v4
        • Upgrade to v3
      • Update your models' definition
      • Monitor your Forest's status
      • Manage your Forest Admin environments programmatically
      • Changing your domain name
      • Migrate to the new role system
      • Push your new version to production
    • Databases
      • Use a demo SQL database
      • Use a demo MongoDB database
      • Populate a postgreSQL database on Heroku
      • Connect to a read replica database
      • Plug multiple schemas
      • Add new databases
      • Manage SQL views
    • Settings
      • Customize your /forest folder
      • Disable automatic Forest Admin schema update
      • Include/exclude models
      • Display extensive logs
      • Laravel specific settings
    • Releases Support
    • Other documentations
Powered by GitBook
On this page
  • Relationships
  • What is a relationship?
  • Adding relationships (databases only)
  • Relationship generation rules

Was this helpful?

  1. Reference Guide
  2. Models

Relationships

PreviousEnrich your modelsNextCreate a Smart relationship

Last updated 1 year ago

Was this helpful?

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 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 v1.

If you’re using a Flask agent, go to the 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 v3.

If you’re using a Symfony agent, go to the 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)

  • belongsTo or hasOne(2)

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:

Adding a hasMany relationship

/models/customers.js
module.exports = (sequelize, DataTypes) => {
  const Customer = sequelize.define('customers',
    ...
  );

  Customer.associate = (models) => {
    Customer.hasMany(models.orders);
  };

  return Customer;
};
/models/customers.js
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:

Once you've added your relationship(s) in your model(s), they will only be taken into account after you restart your server.

Adding a hasOne relationship

In 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".

/models/customers.js
module.exports = (sequelize, DataTypes) => {
  const Customer = sequelize.define('customers',
    ...
  );

  Customer.associate = (models) => {
    Customer.hasOne(models.addresses);
  };

  return Customer;
};
/models/customers.js
module.exports = (mongoose, Mongoose) => {
  const schema = Mongoose.Schema({
    ...
    'address': { type: Mongoose.Schema.Types.ObjectId, ref: 'addresses' },
    ...
  }, {
    timestamps: true,
  });

  return mongoose.model('customers', schema, 'customers');
};

Don't forget to restart your server for your newly added relationships to be taken into account.

Adding a belongsTo relationship

On our Live Demo example, the Address model has a foreignKey customer_id that points to the Customer. In other words, an addressbelongsTo a customer.

/models/addresses.js
module.exports = (sequelize, DataTypes) => {
  const Address = sequelize.define('addresses',
    ...
  );

  Address.associate = (models) => {
    Address.belongsTo(models.customers);
  };

  return Address;
};
/models/addresses.js
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');
};

Don't forget to restart your server for your newly added relationships to be taken into account.

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:

/models/addresses.js
...
Address.associate = (models) => {
  Address.belongsTo(models.customers, {
    foreignKey: 'fk_companyname'
    targetKey: 'name'
  });
};
...

Adding a 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.

/models/user-projects.js
...
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',
  });
};
...
/models/users.js
...
Users.associate = (models) => {
  Users.belongsToMany(models.projects, {
    through: 'userProjects',
    foreignKey: 'userId',
    otherKey: 'projectId',
  });
};
...
/models/projects.js
...
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.

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 to create new ones.

If you installed Forest Admin directly on a database, then most relationships should have been . However, depending on your database nature and structure, you may have to add some manually.

on adding relationships in your models (SQL)

on adding relationships in your models (Mongodb)

In our , a customer can have multiple orders. In that case, we have to use a hasMany relationship.

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 .

This is explained in .

Rails documentation
Sequelize's documentation
Mongoose's documentation
Live demo
Sequelize's documentation
automatically generated
section below
@forestadmin/agent
forestadmin-agent-django
forestadmin-agent-flask
forestadmin/laravel-forestadmin
forestadmin/symfony-forestadmin