Build a to-do application

Developers often build a to-do app to learn a new database because it is a straightforward project that shows the basic capabilities of the database.

In this guide you build a ToDo app and learn the following Fauna core concepts.

  • Create, Read, Update, Delete (CRUD) in Fauna

  • Query patterns

  • Database relationships

This guide assumes that you have already created a Fauna account and have completed the Fauna quick start guide.

Create collections

Create a new database from your dashboard. Navigate to the Shell window of your database. Write and execute the following FQL code to create a new Collection called User.

Collection.create({
  name: 'User'
})
{
  name: "User",
  coll: Collection,
  ts: Time("2024-01-30T06:06:17.475Z"),
  constraints: [],
  indexes: {}
}

Next, create a new collection called Todo. Run the following FQL code in the Shell.

Collection.create({
  name: "Todo"
})
{
  name: "Todo",
  coll: Collection,
  ts: Time("2024-01-30T06:33:36.220Z"),
  indexes: {},
  constraints: []
}

A user has many todo items. There is a one-to-many relationship between a user and todo items.

Create documents

Run the following FQL code to create a new user document in the User collection.

User.create({
 name: "William T",
 email: "ryker@enterprise.com"
})
{
  id: "388327586567028802",
  coll: User,
  ts: Time("2024-01-30T06:41:35.660Z"),
  name: "William T",
  email: "ryker@enterprise.com"
}

Next, create two todo items for the user. Run the following FQL code to create these items.

Todo.create({
 title: "Get Milk",
 status: "Pending"
})

Todo.create({
 title: "Do Laundry",
 status: "Pending"
})

Read documents

You can get all the documents in a collection by calling the .all() method. The following code shows how you get all the todos. Run the following code snippet in the Dashboard Shell.

Todo.all()
{
  data: [
    {
      id: "388467097679691849",
      coll: Todo,
      ts: Time("2024-01-31T19:39:03.850Z"),
      title: "Get Milk",
      status: "Pending"
    },
    {
      id: "388467097679692873",
      coll: Todo,
      ts: Time("2024-01-31T19:39:03.850Z"),
      title: "Do Laundry",
      status: "Pending"
    }
  ]
}

To get a document by its ID, you can use the byId() method. The following code demonstrates how to query a document by ID. In the following FQL code you query the todo item with the ID 388467097679691849.

Todo.byId('388467097679691849')
{
  id: "388467097679691849",
  coll: Todo,
  ts: Time("2024-01-31T19:39:03.850Z"),
  title: "Get Milk",
  status: "Pending"
}

You can also query documents by fields using the where() method of FQL. You can find the user document where the email field equals ryker@enterprise.com with the following FQL code.

User.where(.email == 'ryker@enterprise.com')
{
  data: [
    {
      id: "388327586567028802",
      coll: User,
      ts: Time("2024-01-30T06:41:35.660Z"),
      name: "William T",
      email: "ryker@enterprise.com"
    }
  ]
}

Notice that the where() method returns a Set of documents. You can use the first() method if you want to get a single document. Following is an example. In this scenario you get the first result.

User.where(.email == 'ryker@enterprise.com').first()
{
  id: "388327586567028802",
  coll: User,
  ts: Time("2024-01-30T06:41:35.660Z"),
  name: "William T",
  email: "ryker@enterprise.com"
}

Update documents

You use the update() method to update documents. Following is an example. In the following FQL code, you update the todo item with the ID 388467097679691849 and update the status field to Done.

let todo = Todo.byId("360941936862822477")
todo.update({
 status: "Done"
})
{
  id: "360941936862822477",
  coll: Todo,
  ts: Time("2023-04-03T03:43:10.010Z"),
  title: "Get Milk",
  status: "Done",
}

Delete documents

To delete a document you run the delete() method. Following is an example to delete a todo item.

let todo = Todo.byId("388467097679691849")
todo?.delete()
Todo.byId("388467097679691849") /* deleted */

Database relationship

The User and Todo collections have a one-to-many relationship. A user can have many todos. To define this relationship, you can create a new field in the Todo collection and have a reference to the user to whom it belongs. The following code establishes a one-to-many relationship between a user and todos.

let auser = User.byId("388327586567028802")

Todo.create({
 title: "Car Wash",
 status: "Pending",
 owner: auser
})

Todo.create({
 title: "Pick up the phase modulator",
 status: "Pending",
 owner: auser
})
{
  id: "388472684753716297",
  coll: Todo,
  ts: Time("2024-01-31T21:07:52.100Z"),
  title: "Pick up the phase modulator",
  status: "Pending",
  owner: User.byId("388327586567028802")
}

To get all the todos for a particular user, you can run the following query.

let auser = User.byId("388327586567028802")
Todo.all().where(.owner == auser)
{
  data: [
    {
      id: "388472684753715273",
      coll: Todo,
      ts: Time("2024-01-31T21:07:52.100Z"),
      title: "Car Wash",
      status: "Pending",
      owner: User.byId("388327586567028802")
    },
    {
      id: "388472684753716297",
      coll: Todo,
      ts: Time("2024-01-31T21:07:52.100Z"),
      title: "Pick up the phase modulator",
      status: "Pending",
      owner: User.byId("388327586567028802")
    }
  ]
}

You can also apply further filters. You can run the following query to get all the todos in pending status with the word Car in the title.

let auser = User.byId("388327586567028802")
Todo.all()
  .where(.owner == auser)
  .where(.status == "Pending" && .title.includes("Car"))
{
  data: [
    {
      id: "388472684753715273",
      coll: Todo,
      ts: Time("2024-01-31T21:07:52.100Z"),
      title: "Car Wash",
      status: "Pending",
      owner: User.byId("388327586567028802")
    }
  ]
}

You can also retrieve the user information for a to-do item when you query the to-do item. Following is an example.

Todo.byId("388472684753715273") {
  owner
}
{
  owner: {
    id: "388327586567028802",
    coll: User,
    ts: Time("2024-01-30T06:41:35.660Z"),
    name: "William T",
    email: "ryker@enterprise.com"
  }
}

You can also retrieve selected fields and related entities of the document. If you want the title and status from a todo and the name of the owner, you can do so. Following is an example of such a query.

Todo.byId("388472684753715273") {
  title,
  status,
  owner {
   name
  }
}
{
  title: "Car Wash",
  status: "Pending",
  owner: {
    name: "William T"
  }
}

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!