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
1
A filter that sits at the "authors" level implies that you are filtering the authors, not the books that they've written. So Scenario 2 would return all authors named "Lewis" that have written a book named "Narnia". It would also return all books that this author has written. That's why IMO Option 3 is the way to go – you'd find all authors named Lewis, and then filter their books to only include ones named "Narnia". Under the hood the engine can optimize the DB queries, so you shouldn't worry about joins when designing the API. Never worked with DGS though, this is only my GQL knowledge.
1 hour ago