I am building an API using Strawberry GraphQL and FastAPI. I was thinking about providing query with filters attached to the nested field, for example:
query {
users {
pets(type: DOG) {
name
}
}
I couldn't find a way to implement it though. I saw examples were similar problems were solved with filter on the top level like:
query {
users(where: {pets: {type: DOG}) {
pets(type: DOG) {
name
}
}
Is the first query an allowed pattern in GraphQL at all? If so, how can it be implemented in Strawberry?
In GraphQL, the first query pattern you mentioned—filtering nested fields directly—is not typically supported out of the box. GraphQL queries are usually designed to specify filters at the top level. However, you can implement similar functionality in your API by designing your schema carefully and using resolvers.
Here's how you can implement a solution for your FastAPI and Strawberry GraphQL setup:
Step 1: Define Your Models
Assuming you have User and Pet models, you might start with something like this:
from typing import List
import strawberry
@strawberry.type
class Pet:
name: str
type: str # You can use an enum for types
@strawberry.type
class User:
id: int
name: str
pets: List[Pet]
Step 2: Define Your Query Type
Next, create a query type that includes a resolver for users and their pets:
@strawberry.type
class Query:
@strawberry.field
def users(self, type: str = None) -> List[User]:
# Replace this with your actual data fetching logic
users_data = [
User(id=1, name="Alice", pets=[Pet(name="Buddy", type="DOG"), Pet(name="Whiskers", type="CAT")]),
User(id=2, name="Bob", pets=[Pet(name="Max", type="DOG")])
]
if type:
for user in users_data:
user.pets = [pet for pet in user.pets if pet.type == type]
return users_data
Step 3: Update the Schema
Finally, you can create your schema and integrate it with FastAPI:
import strawberry
from fastapi import FastAPI
from strawberry.fastapi import GraphQLRouter
schema = strawberry.federation.Schema(query=Query)
graphql_app = GraphQLRouter(schema)
app = FastAPI()
app.include_router(graphql_app, prefix="/graphql")
Query Example
With this setup, you can now query for users and filter their pets by type at the top level like this:
query {
users(type: "DOG") {
pets {
name
}
}
}
Filtering at the Top Level: Since GraphQL doesn’t support filtering nested fields directly in the query, we provided a type parameter in the users resolver.
Dynamic Resolvers: The resolver filters pets based on the provided type before returning the users.
This method adheres to GraphQL best practices while still allowing you to achieve the desired filtering effect. If you want more complex nested filtering, you might need to expand your query parameters and logic accordingly.