This is the last section of the tutorial where you’ll implement the finishing touches on your API. The goal is to allow clients to constrain the list of Link
elements returned by the feed
query by providing filtering and pagination parameters.
Thanks to Prisma, you’ll be able to implement filtering capabilities to your API without major effort. Similar to the previous chapters, the heavy-lifting of query resolution will be performed by the powerful Prisma engine. All you need to do is delegate incoming queries to it.
The first step is to think about the filters you want to expose through your API. In your case, the feed
query in your API will accept a filter string. The query then should only return the Link
elements where the url
or the description
contain that filter string.
Next, you need to update the implementation of the feed
resolver to account for the new parameter clients can provide.
If no filter
string is provided, then the where
object will be just an empty object and no filtering conditions will be applied by the Prisma engine when it returns the response for the links
query.
In case there is a filter
carried by the incoming args
, you’re constructing a where
object that expresses our two filter conditions from above. This where
argument is used by Prisma to filter out those Link
elements that don’t adhere to the specified conditions.
Notice that the Prisma
binding object translates the above function call into a GraphQL query that will look somewhat similar to this. This query is sent by the Yoga server to the Prisma API and resolved there:
query ($filter: String) {
links(where: {
OR: [{ url_contains: $filter }, { description_contains: $filter }]
}) {
id
url
description
}
}
Note: You can learn more about Prisma’s filtering capabilities in the docs. Another way explore those is to use the Playground of the Prisma API and read the schema documentation for the
where
argument or experiment directly by using the autocompletion features of the Playground.
That’s it already for the filtering functionality! Go ahead and test your filter API - here’s a sample query you can use:
query {
feed(filter: "Prisma") {
id
description
url
}
}
Pagination is a tricky topic in API design. On a high-level, there are two major approaches regarding how it can be tackled:
Prisma supports both pagination approaches (read more in the docs). In this tutorial, you’re going to implement limit-offset pagination.
Note: You can read more about the ideas behind both pagination approaches here.
Limit and offset are called differently in the Prisma API:
first
, meaning you’re grabbing the first x elements after a provided start index. Note that you also have a last
argument available which correspondingly returns the last x elements.skip
, since you’re skipping that many elements in the list before collecting the items to be returned. If skip
is not provided, it’s 0
by default. The pagination then always starts from the beginning of the list (or the end in case you’re using last
).So, go ahead and add the skip
and first
arguments to the feed
query.
Now, on to the resolver implementation.
Really all that’s changing here is that the invocation of the links
query now receives two additional arguments which might be carried by the incoming args
object. Again, Prisma will do the hard work for us 🙏
You can test the pagination API with the following query which returns the second Link
from the list:
query {
feed(
first: 1
skip: 1
) {
id
description
url
}
}
With Prisma, it is possible to return lists of elements that are sorted (ordered) according to specific criteria. For example, you can order the list of Link
s alphabetically by their url
or description
. For the Hackernews API, you’ll leave it up to the client to decide how exactly it should be sorted and thus include all the ordering options from the Prisma API in the API of your Yoga server. You can do so by directly referencing the LinkOrderByInput
enum from the Prisma database schema. Here is what it looks like:
enum LinkOrderByInput {
id_ASC
id_DESC
description_ASC
description_DESC
url_ASC
url_DESC
updatedAt_ASC
updatedAt_DESC
createdAt_ASC
createdAt_DESC
}
It represents the various ways how the list of Link
elements can be sorted.
The implementation of the resolver is similar to what you just did with the pagination API.
Awesome! Here’s a query that sorts the returned links by their creation dates:
query {
feed(orderBy: createdAt_ASC) {
id
description
url
}
}
Link
elementsThe last thing you’re going to implement for your Hackernews API is the information how many Link
elements are currently stored in the database. To do so, you’re going to refactor the feed
query a bit and create a new type to be returned by your API: Feed
.
Link
elements. This is similar to what you did before except that you’re now hardcoding the selection set of the query again and only retrieve the id
fields of the queried Link
s. In fact, if you tried to pass info
here, the API would throw an error (read this article to understand why).linksConnection
query from the Prisma database schema to retrieve the total number of Link
elements currently stored in the database. You’re hardcoding the selection set to return the count
of elements which can be retrieved via the aggregate
field.count
can be returned directly. The links
that are specified on the Feed
type are not yet returned - this will only happen at the next resolver level that you still need to implement. Notice that because you’re returning the linkIds
from this resolver level, the next resolver in the resolver chain will have access to these.The last step now is to implement the resolver for the Feed
type.
Here is where the links
field from the Feed
type actually gets resolved. As you can see, the incoming parent
argument is carrying the linkIds
which were returned on the previous resolver level.
The last step is to include that new resolver when instantiating the GraphQLServer
.
You can now test the revamped feed
query as follows:
query {
feed {
count
links {
id
description
url
}
}
}