User-defined functions
User-defined functions (UDF) can be exposed through the GraphQL
API by using the @resolver
directive at fields in the Query and Mutation types. This directive has
no effect if placed elsewhere.
The UDF must have the same arguments, in the same order, as its associated field in the GraphQL schema. There is no association between the arguments' names in the GraphQL schema and the arguments' names in the UDF definition. When a UDF field is queried, the GraphQL API simply calls the underlying UDF with the given arguments.
The UDF result type must be a GraphQL-compatible type. If an object is returned, an equivalent type must exist in the GraphQL schema to allow users to select which fields to return. Embedded types can be used to map return types that are not associated with any existing type.
UDFs with pagination support must return a database page. In addition to the function arguments, the API calls the UDF with three additional arguments appended the query’s arguments:
-
size
: the requested page size -
after
: the database forward cursor -
before
: the database backwards cursor
A UDF’s implementation must account for these additional arguments and
call the appropriate form of the FQL
Paginate
function to return a
database page to the GraphQL API.
Examples
A UDF that returns a scalar type:
The following is a UDF, using Fauna Shell syntax, that returns a scalar type:
CreateFunction({
name: "say_hello",
body: Query(Lambda(["name"],
Concat(["Hello ", Var("name")])
))
})
A GraphQL schema that uses the UDF:
type Query {
sayHello(name: String!): String! @resolver(name: "say_hello")
}
With these in place, when you run the following query:
{
sayHello(name: "Jane")
}
The result should be:
{
"data": {
"sayHello": "Hello Jane"
}
}
A UDF that returns an embedded object
The following is a UDF, in Fauna Shell syntax, that returns an embedded object:
CreateFunction({
name: "sample_obj",
body: Query(Lambda([], {
time: Time("now"),
sample: true
}))
})
A GraphQL schema that uses the UDF:
type SampleObj @embedded {
time: Time!
sample: Boolean!
}
type Query {
sampleObj: SampleObj! @resolver(name: "sample_obj")
}
With these in place, when you run the following query:
{
sampleObj {
time
sample
}
}
The result should be:
{
"data": {
"sampleObj": {
"time": "2019-06-14T17:42:54.001987Z",
"sample": true
}
}
}
A UDF that returns a database page
The following is a UDF (along with a Collection and Index), in Fauna Shell syntax, that returns a database page, so that repeated querying can retrieve all of the paginated results.
CreateCollection({
name: "users"
})
CreateIndex({
name: "vip_users",
source: Collection("users"),
terms: [{ field: [ "data", "vip" ] }]
})
CreateFunction({
name: "vip_users",
body: Query(Lambda(["size", "after", "before"],
Let(
{
match: Match(Index("vip_users"), true),
page: If(
Equals(Var("before"), null),
If(
Equals(Var("after"), null),
Paginate(Var("match"), { size: Var("size") }),
Paginate(Var("match"), { size: Var("size"), after: Var("after") })
),
Paginate(Var("match"), { size: Var("size"), before: Var("before") }),
)
},
Map(Var("page"), Lambda("ref", Get(Var("ref"))))
)
))
})
A GraphQL schema that uses the UDF:
type User @collection(name: "users") {
username: String!
vip: Boolean!
}
type Query {
vips: [User!] @resolver(name: "vip_users", paginated: true)
}
With these in place, when you run the following query:
{
vips(
_size: 2
_cursor: "2DOB2DRyMjM1MTcwOTY5MDA0NTQwNDIzgWV1c2Vyc4FnY2xhc3Nlc4CAgIA="
) {
data {
username
}
after
before
}
}
The result should be:
{
"data": {
"vips": {
"data": [
{ "username": "Mary" },
{ "username": "Ted" }
],
"after": null,
"before": "2DKB2DRyMjM1MTcwOTY5MDA0NTQwNDIzgWV1c2Vyc4FnY2xhc3Nlc4CAgIA="
}
}
}
Was this article helpful?
We're sorry to hear that.
Tell us how we can improve!
documentation@fauna.com
Thank you for your feedback!