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 Example

A book has one author.

An author writes many books.

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

The following gives you examples of how to implement the different relationships in Fauna.

One-to-one

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 applicable collection, create an instance of a grower and a detailed instance that includes the company name and grower location:

    let grower = Growers.create({name: "nishant gurjer"})
    let details = GrowerDetails.create({
      owner: grower,
      company: "Vital Signs Advisory & Management Works Llp",
      location: "Bengaluru Karnataka, INDIA"
     })
    details
    {
      id: "369270283448616001",
      coll: GrowerDetails,
      ts: Time("2023-07-03T22:13:55.140Z"),
      owner: Growers.byId("369270283448614977"),
      company: "Vital Signs Advisory & Management Works Llp",
      location: "Bengaluru Karnataka, INDIA"
    }

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

One-to-many

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"
        }
      ]
    }

Many-to-many

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 constraints definition documentation for more information about using constraints to enhance search and selection.

Continue to the Improve performance with indexes tutorial to learn how to make your queries more efficient.

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!