We are using Apollo Router + Netflix DGS to build federated graphql services. Suppose that we have a common relational database right now for books and authors, but want to move towards a microservice architecture, where books and authors are stored separately in their own database.
Suppose that I have the following graphql schema:
type Author {
name: String
books: [Book]
}
type Book {
title: String!
}
type Query {
getAuthors(name: String!, title: String) {
authors: [Authors]
}
}
Here are two query scenarios / results:
Scenario 1 - returns multiple authors named Lewis and list of books (0:N) associated with each author named Lewis
query {
getAuthors("Lewis") {
name
books
}
}
Scenario 2
query {
getAuthors(name: "Lewis", title: "Cronicles of Narnia") {
name
books
}
}
In a single relational database where books and authors are stored together, my query could be:
Single Relational DB Query
select * from authors a
inner
join books b on a.id = b.author_id where name = "Lewis" and title = "Cronicles of Narnia";
select * from authors a
left
join books b where a.id = b.author_id and name = "Lewis" and title = "Cronicles of Narnia";
In my future, microservice, multi-database where books and authors are stored seperately, my query could be:
Microservice / Multi-database Query:
select * from authors where name = "Lewis";
select * from books where title = "Cronicles of Narnia";
- Then allow Apollo or Netflix DSG to join at the application level.
Question 1
What should my Scenario 2 graphql query return? I actually need to support both options below in different scenarios, so is there a different way to write the query for each?
Option 1) just one author named Lewis and just one book named "Cronicles of Narnia"? (this is the INNER JOIN)
Option 2) a list of authors named Lewis and, where linked to a specific "Lewis", append the book(s) named "Cronicles of Narnia"? (this is the LEFT JOIN)
Question 2
In my future, multi-database scenario, how would graphql (Apollo, Netflix DSG) behave? Is it more like Option 1 or Option 2? As mentioned, would need to support both.
Question 3
I've also seen a similar query written like this. Do these queries have different meanings? Is this widely supported?
query {
getAuthors(name: "Lewis") {
name
books (title: "Cronicles of Narnia")
}
}
Thanks!
Justin
GraphQL doesn't really care/understand if you're sitting on top of a single DB or over multiple microservices - it's the job of your resolvers to map GraphQL queries into one or more db/microservice queries.
Semantically:
Should return a 400 error since you specified
books
but didn't include any fields from it.Should return all authors named "Lewis" and the title of every one of their books.
should return every author whose name is "Lewis" and who has written at least one book named "Chronicles of Narnia"
should return every author named "Lewis" and for each of those the title of any book whose title is "Chronicles of Narnia". Note that in this case you won't have the opportunity to filter the authors based on the book title since the field resolver runs after the query resolver and a child can't filter its parent (Contrary to @Avius' comment)