Define relationships

Relationships establish associations between documents in two or more collections.

With support for the following three types of relationships, Fauna gives you the capabilities of a relational database with the flexibility of a NoSQL database:

Relationship type Example

A book has one author.

An author writes many books.

A reader has many books, and a book has many readers.

The following shows examples of how to implement the different kinds of relationships between documents. The examples use FQL directly to create the collections involved in the relationships. You can also use the Dashboard or CLI schema management in keeping with best practices for defining schema:

  • To define a collection using the Dashboard, select the database, and with the Collections menu item selected in the lower panel for the database, click the Create Collection (+) symbol and define the collection properties.

  • To define a collection using the CLI, define the collection in a .fsl schema file and push the file to Fauna. See Get started with FSL for more information.

Define a one-to-one relationship

A one-to-one relationship exists between two entities when a document exists in one collection and has one and only one associated document in another collection.

This example continues to build on the coffee growers theme and associates a collection of growers with details about each grower.

  1. Create a collection to hold the list of growers:

    Collection.create({ name: "Growers" })
    {
      name: "Growers",
      coll: Collection,
      ts: Time("2023-07-03T21:50:27.190Z"),
      constraints: [],
      indexes: {}
    }
  2. Create a collection to hold detailed information about each grower:

    Collection.create({name: "GrowerDetails"})
    {
      name: "GrowerDetails",
      coll: Collection,
      ts: Time("2023-07-03T22:10:13.390Z"),
      constraints: [],
      indexes: {}
    }
  3. In the Growers collection, create an instance of a grower, and in the GrowerDetails collection, create a document that references the grower instance. Display the result:

    let grower = Growers.create({name: "nishant gurjer"})
    let details = GrowerDetails.create({
      owner: grower,
     })
    details
    {
      id: "369270283448616001",
      coll: GrowerDetails,
      ts: Time("2023-07-03T22:13:55.140Z"),
      owner: Growers.byId("369270283448614977"),
    }

    Setting the owner: grower link in the details document associates the documents in the two collections.

  4. Using projection, notice how Fauna dereferences the relationship when you select a field in a related document:

    GrowerDetails.all().first() {owner}
    {
      owner: {
        id: "379625160749088836",
        coll: Growers,
        ts: Time("2023-07-03T21:13:54.730Z"),
        name: "nishant gurjer"
      }
    }

Define a one-to-many relationship

A one-to-many relationship exists between two entities when a document in the first collection is associated with one or more documents in the second collection. Conversely, a document in the second collection can be associated with one and only one entry in the first collection.

This example gets all coffee bean species that belong to the Rubiaceae flowering plant family.

  1. Create a Family collection and add a Rubiaceae plant family document to the collection:

    Collection.create({name: "Family"})
    {
      name: "Family",
      coll: Collection,
      ts: Time("2023-07-11T18:22:04.250Z"),
      constraints: [],
      indexes: {}
    }

    Family.create({
        name: "Rubiaceae",
    })
    {
      id: "369980560237396036",
      coll: Family,
      ts: Time("2023-07-11T18:23:27.906Z"),
      name: "Rubiaceae"
    }
  2. Create a Species collection and add the Arabica and Robusta coffee species to the collection, including a reference to their Rubiaceae family membership:

    Collection.create({name: "Species"})
    {
      name: "Species",
      coll: Collection,
      ts: Time("2023-07-03T20:37:56.760Z"),
      indexes: {},
      constraints: []
    }

    Species.create({
        name: "Arabica",
        family: "Rubiaceae",
    })
    {
      id: "369264277061632065",
      coll: Species,
      ts: Time("2023-07-11T18:25:57.980Z"),
      name: "Arabica",
      family: "Rubiaceae"
    }

    Species.create({
        name: "Robusta",
        family: "Rubiaceae",
    })
    {
      id: "369264300265570369",
      coll: Species,
      ts: Time("2023-07-11T18:26:42.900Z"),
      name: "Robusta",
      family: "Rubiaceae"
    }
  3. Get all the coffee species that belong to the Rubiaceae family:

    Species.where(.family == "Rubiaceae")
    {
      data: [
        {
          id: "369264277061632065",
          coll: Species,
          ts: Time("2023-07-11T18:25:57.980Z"),
          name: "Arabica",
          family: "Rubiaceae"
        },
        {
          id: "369264300265570369",
          coll: Species,
          ts: Time("2023-07-11T18:26:42.900Z"),
          name: "Robusta",
          family: "Rubiaceae"
        }
      ]
    }

Define many-to-many relationships

A many-to-many relationship exists between documents when for every document in the first collection, there are multiple related documents in the second collection, and for every document in the second collection, there are multiple related documents in the first collection.

In this example, a country can grow many species of coffee bean, and a species can be grown in many different countries. This uses the Species collection created in the previous example.

  1. Create a Country collection of countries that grow coffee beans:

    Collection.create({name: "Country"})
    {
      name: "Country",
      coll: Collection,
      ts: Time("2023-07-03T22:35:31.560Z"),
      constraints: [],
      indexes: {}
    }
  2. Add Ethiopia and Guatemala to the list of countries:

    [{name: "Ethiopia"}, {name: "Guatemala"}].map(Country.create)
      {
        id: "369271717354274884",
        coll: Country,
        ts: Time("2023-07-05T14:07:47.650Z"),
        name: "Ethiopia"
      },
      {
        id: "369271742511710276",
        coll: Country,
        ts: Time("2023-07-05T14:07:47.650Z"),
        name: "Guatemala"
      }
    ]

    See map() for reference documentation about the Array map() method.

  3. Create a CountryList collection to hold all the countries that grow a given coffee bean species.

    Collection.create({name: "CountryList"})
    {
      name: "CountryList",
      coll: Collection,
      ts: Time("2023-07-03T22:36:20.590Z"),
      indexes: {},
      constraints: []
    }
  4. Using the byId() method to get each country in the Country collection and populate CountryList with details about the country, including the species of coffee bean grown, which is in the Species collection.

    Selecting on species in the list of countries in the CountryList collection, list the location of all matching countries:

    let species = Species.byId("369264277061632065")
    let country = Country.byId("369271717354274884")
    
    CountryList.create({
        location: country,
        type: species,
        awards: [
          "gold",
          "silver",
        ]
    })
    
    let country2 = Country.byId("369271742511710276")
    
    CountryList.create({
        location: country2,
        type: species,
        awards: [
          "blue",
          "yellow",
        ]
    })
    
    let species = Species.byId("369264277061632065")
    let countries = CountryList.all().where(.type == species)
    
    countries {
        location
    }
    {
      data: [
        {
          location: {
            id: "369271717354274884",
            coll: Country,
            ts: Time("2023-07-03T22:36:42.610Z"),
            name: "Ethiopia"
          }
        },
        {
          location: {
            id: "369271742511710276",
            coll: Country,
            ts: Time("2023-07-03T22:37:06.610Z"),
            name: "Guatemala"
          }
        }
      ]
    }

Next steps

See the unique constraint reference for ways to use unique constraints to facilitate more powerful search and selection capabilities.

Continue to the Use indexes for more efficient queries tutorial to learn how to make your queries more efficient by using indexes instead of the where() method.

Is this article helpful? 

Tell Fauna how the article can be improved:
Visit Fauna's forums or email docs@fauna.com

Thank you for your feedback!