In the previous section, you implemented common access patterns in Fauna with GraphQL. In this section, you learn how GraphQL resolvers work and create a custom resolver using a user-defined function (UDF) and the @resolver directive in Fauna.
In the previous section you learned that Fauna can automatically generate a resolver to list all documents of a given type. Fauna also provides you with the flexibility to create your own resolvers and run custom business logic inside the data layer.
According to Apollo GraphQL:
A resolver is a function that’s responsible for populating the data for a single field in your schema. Whenever a client queries for a particular field, the resolver for that field fetches the requested data from the appropriate data source.
When using Fauna, the function is a UDF, and the data source is Fauna.
When you create any GraphQL service you create resolver functions in your application layer. In a typical GraphQL server, a resolver function retrieves data from a database, performs custom business logic in the application layer, and returns a response. The following diagram demonstrates this traditional GraphQL server data flow.
In other GraphQL servers you query data from a database, which introduces a slight delay in the response. In Fauna, there is no application layer. Instead, Fauna exposes its GraphQL interface directly to the client. You write your resolvers as UDFs using Fauna’s native Fauna Query Language (FQL) and your resolver functions run directly in the database layer.
The following diagram demonstrates the same data flow when implemented with Fauna.
Navigate to the Functions tab in the Fauna dashboard and choose New Function to create a new UDF.
GetStoreCount
.Query(
Lambda(
[],
Count(Documents(Collection("Store")))
)
)
UDFs are written in the Fauna Query Language (FQL) - the functional programming language at the heart of Fauna. FQL supports function composition, so you can compose complex expressions from simpler components.
The Query(Lambda(…)) wrapper is required for all UDFs.
Lambda takes two arguments. * A single variable or array of variables. In this case, your UDF does not accept any variables, so you define an empty array. * The body of the UDF, written as a valid FQL expression. The FQL expression in this UDF counts the number of documents in the “Store” collection.
Note: Count requires an index scan which runs in O(n) time. Do not call use this approach in production workloads!
Update your schema to add a countStores query using the @resolver directive to invoke the GetStoreCount UDF or download the linked schema.
type Query {
findOwnerByEmail(email: String): [Owner] @relation(name: "OwnerByEmail")
listOwners: [Owner]
# Add the following line
countStores: Int @resolver(name: "GetStoreCount")
}
Replace your schema and review the Docs section of your GraphQL playground. Notice the new countStores query that appears.
Run the following query to count how many stores have been created in your application.
query {
countStores
}
{
"data": {
"countStores": 1
}
}
In this section, you learned how GraphQL resolvers work and created a custom resolver using a UDF in Fauna.
In the next section, you learn how to authenticate users and control access to resources using GraphQL and Fauna.