Data Relationships

Data Relationship

In our application, a user can create many videos. Therefore we have a one-to-many relationship between users and videos.

Data relationships

A user is also able to share videos with other users. We can create a many-to-many relationship between the User and Permission collections. A record in the Permission collection has a reference (left join) to a record in the User collection and another reference (right join) to a record in the Video collection.

Video collection

one-to-many

Let's explore how to do one-to-many relationships in Fauna. Head back to the Fauna dashboard and open a new web shell. The following is an example of creating a one-to-many relationship between a user and a video document in FQL.

let user = User.firstWhere(.email == 'work@email.com')
user
Video.create({
  title: "New Video",
  duration: 100,
  author: user
})

The FQL code here is self-explanatory. It fetches a user with the email work@email.com and sets it to a user variable. Then it creates a new Video and sets the author field as a reference to the user variable.

We can run the following query to query all the videos authored by a particular user.

let user = User.firstWhere(.email == "work@email.com")
Video.where(.author == user)

We can also locate the user information of the author while querying for a Video.

Video.byId("370884791225024589") {
  id,
  title,
  author {
    id,
    email
  }
}

Note: If you are familiar with GraphQL, you might recognize the above syntax. While designing the Fauna Query Language, we took a lot of inspiration from GraphQL. Similar to GraphQL, FQL also focuses on reducing over-fetching when projecting specific fields we need in our resource set.

Another thing to note in the query above is the long id number. This is an internal metadata element generated by Fauna for every document, it is a unique identifier for each document in the database. This id can be used as a primary key, and Fauna will always ensure its uniqueness.

We can now add the updated FQL query to our code to establish this one-to-many relationship. Make the following change to src/app/record/page.js file.

// src/app/record/page.js
 
// ...
export default function Record() {
    // ... 
    const handleRecordedVid = async (blob) => {
        try {
            const newVid = await client.query(fql`
                **let user = User.byId(${userInfo.id})
                Video.create({
                    title: ${new Date().toISOString()},
                    author: user
                })**
            `)
            console.log('newVid', newVid)
 
            await fetch(`https://backend.shadidhaque2014.workers.dev/${newVid.data.id}`, {
                method: 'PUT',
                headers: {
                    'Content-Type': 'video/webm',
                    'X-Custom-Auth-Key': 'supersecret'
                },
                body: blob
            })
        } catch (error) {
					// ... Rest of the code
        }
    }
  // ... Rest of the code
}

πŸ‘¨β€πŸ«Β link to code

many-to-many

Next, let’s take a look at how many-to-many relationship works in Fauna. A record in the Permission collection will have two references. The following code demonstrates how to define many-to-many relationships.

let userToShareWith = User.firstWhere(.email == 'work@email.com')
let videoToshare = Video.byId('370841917380886601')
 
Permission.create({
  user: userToShareWith,
  video: videoToshare
})

We can run the following query to determine if a particular user can access a video.

let user = User.byId("368374186628874313")
let video = Video.byId("370841917380886601")
 
Permission.where(.user == user && .video == video)

Last updated on August 5, 2023