Get Count of related documents

Hi

I’m new to fauna and have beginner issues.
I have the following Schema with the types of a List and Todo, where a Todo belongs to a list:

type Todo {
  title: String!
  description: String!
  userId: String!
  list: List! @Relation
  completed: Boolean
}

type List {
  name: String!
  todos: [Todo]!
}

In the frontend I want to do a graphql query to get all lists and foreach list get the name and the count of the associated Todos.
I think i need a user defined function and an index, but I’m unsure how it all relates.

Can you point me to sources, where I can read more about it.
Thanks in advance

Hi @ms007 and welcome! :wave:

To perform any kind of compute which is accessible in your GraphQL API, you will need to add a Query field and implement a customer resolver with the @resolver directive. The customer resolver is defined using FQL (v4)

The index for the relationship should already be created for you when you upload your schema. Make sure you are using @relation for your fields (all lowercase) and not @Relation.

You can also use the @embedded directive to create a type to return without it being associated with a Collection.

For example, with the following schema:

type Todo {
  title: String!
  description: String!
  userId: String!
  list: List! @relation
  completed: Boolean
}

type List {
  name: String!
  todos: [Todo] @relation
}

type ListSummary @embedded {
  list: List!
  todoCount: Int!
}

type Query {
  summarizeLists: [ListSummary!]! @resolver(name: "summarizeLists", paginated: true)
}

Your query might look like this:

query {
  summarizeLists(_size: 50) {
    data {
      list {
        _id
        name
      }
      todoCount
    }
    after
  }
}

Alternative: Store count of Todos in the List

You can add a field to the List type that stores the count of Todos. This would require you to update the related list every time that a Todo is created or deleted, though. You can do that override by using https://docs.fauna.com/fauna/current/api/graphql/directives/d_generateudfresolvers

Alternative: Use the latest version of FQL (v10)

The latest version of FQL has a projection syntax that makes it similar to GraphQL. So instead of defining some things in GraphQL and some things in FQL, you could define everything and use FQL.

Create Collections and Indexes

Collection.create({ name: "User" })
Collection.create({ name: "List" })
Collection.create({ 
  name: "Todo",
  indexes: {
    byUser: {
      terms: [{ field: "user" }]
    },
    byList: {
      terms: [{ field: "list" }]
    }
  }
})

Create some initial data (Assumes users already exist)

let me = User.byId("368697182365155408")
let list1 = List.create({ name: "My Favorite Things" })

[
  { title: "Raindrops on roses", user: me, list: list1 },
  { title: "Whiskers on kittens", user: me, list: list1 }, 
].map(data => Todo.create(data))

Run the query

List.all().map(list => list {
  id,
  ts,
  name,
  todoCount: Todo.byList(list).count()
})

>> SUCCESS

{
  data: [
    {
      id: "368697327727149137",
      ts: Time("2023-06-27T14:27:01.980Z"),
      name: "My Favorite Things",
      todoCount: 2
    }
  ]
}

Check out the beta for our new dashboard here, and beta documentation here.

Wow. What a detailed answer. Will try it out today.
I’m glad that this answer was created by a human (are you human?) If not i will start today to fear AI :wink:

1 Like

I tryed the first version with the following udf:

Query(
  Lambda(
    [],
    Let(
      {
        lists: Paginate(Match(Index("all_lists"))),
        summaries: Map(
          Var("lists"),
          Lambda(
            "listRef",
            Let(
              {
                list: Get(Var("listRef")),
                todoCount: Count(Match(Index("todos_by_list"), Var("listRef")))
              },
              { list: Var("list"), todoCount: Var("todoCount") }
            )
          )
        )
      },
      Var("summaries")
    )
  )
)

And then calling it in the shell like this:

Call(Function("summarizeLists"))

But I did not tried it from the graphql. Would need to update the udf I think.

To me, the third version looks the cleanest: FQL v10. And I will definitely try it out.

Have marked the answer as the solution. It helped me a lot and improved my knowledge of Fauna a bit again.

Thank you.

1 Like

Haha human, here! I have not been replaced by our AI overlords yet :smiling_face:

I am glad to help! Please feel free to reach out again with other questions or feedback.

This topic was automatically closed 2 days after the last reply. New replies are no longer allowed.