How to filter the inner Nodes with gqlgen - go

I am using gqlgen to generate boilerplate for graphql queries. How do I generate a resolver for the inner nodes?
For instance, I have a Region schema with [school] array but I also need a filter for the school array. School schema contains classes array which again can be filtered by id. The below query would return all the schools and classes. But as mentioned I also need ability to filter the Schools and Classes in the same query.
type Region {
id: ID!
name: String!
schools: [School!]!
}
type School {
id: ID!
name: String!
classes: [class!]!
}
type Query {
regions(id : ID!): [Region!]!
}

Related

How to merge results from two gql queries in to one array of results?

We have two services exposing two sets of schemas, merged in a gateway using Graphql Tools Schema Stitching
Is it possible to merge queries from two services in such a way that it returns combined results?
Example case:
Book service contains data for books
interface Searchable {
id: ID!
}
type Book implements Searchable {
id: ID!
name: String
# other fields
}
type Query {
_search( term: String ): [Searchable]
}
User Service has the data for authors
interface Searchable {
id: ID!
}
type Author implements Searchable {
id: ID!
name: String
# other fields
}
type Query {
_search( term: String ): [Searchable]
}
Gateway
interface Searchable {
id: ID!
}
type Book implements Searchable {
id: ID!
name: String
# other fields
}
type Author implements Searchable {
id: ID!
name: String
# other fields
}
type Query {
search( term: String ): [Searchable]
}
I can recommend using GraphQL-Mesh - it uses tools under the hood, and enables you to easily merge multiple sources (GraphQL and many others), manipulate it and get one GraphQL endpoint / schema

Laravel lighthouse graphql query by relation table value

Is it possible in Laravel lighthouse GraphQL to query by relation table values?
For example, I have defined two types.
type Translation {
id: ID!
form_group_id: Int!
group: Group #hasOne
translation_key: String!
lv: String
en: String
ru: String
}
type Group {
id: ID!
name: String!
translations: [Translation]! #hasMany
}
and I want to query by group name.
The code below is just an example of the idea.
translation(group.name: String! #eq): Translation #find
I have an idea that this, can be possible with custom resolver, but is there a way using built in eloquent resolvers?
Event tho this is an experimental feature, you can use complex where conditions. This will allow you to fetch whatever type by its relation attributes. We use it on our application, and for the use we have, this is working as expected :)

GraphQL query with multiple nested resolvers and mapping fields to arguments

From GraphQL Client's perspective, how do I perform a query with multiple nested resolvers where the fields from the parent are passed as arguments to the child resolver?
Here is a minimal example:
GraphQL Schema:
type Author {
id: ID!
name: String!
}
type Book {
id: ID!
title: String!
releaseDate: String!
}
type Query {
// Returns a list of Authors ordered by name, 'first' indicates how many entries to return
getAllAuthors(first: Int!): [Author]!
// Returns a list of Books ordered by releaseDate, 'first' indicates how many entries to return
getBooksByAuthorId(first: Int! authorId: ID!): [Book]!
}
Is it possible to write a query to get all authors and their last released book? Something around the lines:
query GetAuthorsWithLastBook($first: Int!) {
getAllAuthors(first: $first) {
authorId: id
name
lastBook: getBooksByAuthor(1, authorId) {
title
}
}
}
In the example above, I attempted to alias getAllAuthors.id as authorId and pass the alias down as argument to getBooksByAuthor(...) but that didn't work.
The key aspect of the problem is that I don't know the authorIds beforehand. I could fetch the authors first and build a query to fetch their last book but that will result in multiple queries and that is something I would like to avoid.
Update
A Java Kickstarter example is available here: https://www.graphql-java-kickstart.com/tools/schema-definition/
yes, on the graphql definition, you need to add lastBook in the Author
type Author {
id: ID!
name: String!
lastBook: [Book]
}
Next up u need to write the resolver for the lastBook
const resolvers = {
Query: {
Author {
lastBook: (parent, args) {
const userId = parent.id;
return getBooksByAuthor(userId, 1);
},
}
}
};

How to create a document in FaunaDB with a given _id using GraphQL instead of accepting the auto-generated one

It is possible to do it using FQL, but I can't find any example of a GraphQL mutation that creates a new document in FaunaDB where the _id is defined by the application and not by FaunaDB itself.
Of course I can add my application-generated ID (an uuidv4 for instance) as an additional attribute in the document and create an index for it, but it doesn't seem right considering the document will have another primary key anyway.
You can use resolver directive, associate with a user defined function (UDF) to accept _id as a parameter and then use Create.
Here is an example,
Schema file
type Order {
customerName: String!
price: Float!
}
input OrderInput {
orderID: Int!
customerName: String!
price: Float!
}
type Query {
CreateOrder(data: OrderInput!): Order! #resolver
}
UDF (CreateOrder)
Update(
Function("CreateOrder"),
{
body: Query(Lambda(["orderdata"],
Create(Ref(Collection("Order"), Select(["orderID"],Var("orderdata"))),
{
data: {
customerName: Select(["customerName"], Var("orderdata")),
price: Select(["price"], Var("orderdata"))
}
}
)))})
GraphQL Query

Using nested arguments in GraphQL operations

I have a schema like so:
scalar Date
schema {
query: Query
}
type Query {
user(id: ID!): User
messages(userId: ID!): [ChatMessage!]!
}
type User {
id: ID!
username: String!
email: String!
}
type ChatMessage {
id: ID!
content: String!
time: Date!
user: User!
}
And I want to make an operation where you can get all messages for a user, but since User and ChatMessage are in separate database tables I would need to perform two queries (one to get the ChatMessages and one to get the User), so I thought I should model it like so:
query findMessagesForUser($userId: ID!) {
messages(userId: $userId) {
id
content
user(id: $userId) {
username
email
}
}
}
This returns a parse error on the schema:
GraphQLDocumentError: Unknown argument "id" on field "ChatMessage.user".
So, how do I get the $userId argument passed to the resolver for ChatMessage.user?
In your schema, you’ve defined an id input on your Query.user method. In your query, you are trying to supply an id to the Message.user property, however you haven't defined this input in your schema.
If you wanted to accept an id on ChatMessage.user, you'd need to define it as:
type ChatMessage {
id: ID!
content: String!
time: Date!
user(id: ID!): User
}
However, it wouldn't really make sense (at least to me) to construct a schema this way, I assume there's only one user (author) per message.
As indicated by #xadm, the object you resolved at the ChatMessage level will be passed into the user resolver as the first argument.
Even if you're not exposing ChatMessage.userId in the schema (that's fine), you'd still probably load this up in your back- end (the foreign key value in the ChatMessage table) and set this on the object used to resolve ChatMessage.
This way, you'll (lazy) load user IF that's included in the query, using the userId property of the parent ChatMessage object argument (remember you don't need to expose ChatMessage.userId via the schema, it's just on the object you use to resolve ChatMessage).
I'd consider modelling more like this (filter input used as an additional contrived example):
type Query {
user(id: ID!): User
messages(filter: MessageFilter): [ChatMessage!]!
}
type MessageFilter {
search: String
paging: PagingFilter
}
type PagingFilter {
after: ID!
pageSize: Int!
}
type User {
id: ID!
username: String!
email: String!
messages(filter: MessageFilter): [ChatMessage!]!
}
In your resolver map, you can wire up the same function to resolve messages at the User level and at the Query level. The only difference is you wouldn't have a userId at the Query level.
If consumers want to view/search messages from all users, they use the top level Query messages method.
{
messages({search: 'graphql'}) {
id,
content,
time
}
}
If the consumer wants to view/search one user's messages, go through the top level Query users method into messages.
{
user(id: 3) {
messages({search: 'graphql'}) {
id,
content,
time
}
}
}
The filter example is contrived, but could provide basic paging for loading of messages.
apollographql.com/docs/graphql-tools/resolvers

Resources