What does the GraphQL schema/resolver look like for an object of objects? - graphql

data
{
user_id: 'abc',
movies: {
'111': {
title: 'Star Wars 1'
},
'112': {
title: 'Star Wars 2'
}
}
}
What would the schema and resolver for this look like?
This was my best attempt, but I've never seen an example like this, so really not sure.
schema
type User {
user_id: String
movies: Movies
}
type Movies {
id: Movie
}
type Movie {
title: String
}
resolver
User: {
movies(user) {
return user.movies;
}
},
Movies: {
id(movie) {
return movie;
}
}

You're still missing a Query type, which tells GraphQL where your queries can start. Something like:
type Query {
user(id: String): User
movie(id: String): Movie
}
also, I think for your movies, you should have [Movie] instead of a Movies type and then id inside of it. So get rid of your Movies type and just do this:
type User {
id: String
movies: [Movie]
}
type Movie {
id: String
title: String
}

Related

Github GraphQL API v4 Query on CommitAuthor

I am trying to run the following query on Githubs GraphQL api:
{
user(login: "davekaj") {
id
repositories(first: 10, orderBy: {field: NAME, direction: ASC}) {
nodes {
ref(qualifiedName: "master") {
target {
... on Commit {
history(first: 15, author: "WHAT DO I PUT HERE") {
totalCount
nodes {
additions
author {
name
user {
id
}
}
committedDate
deletions
}
}
}
}
}
}
}
}
}
It wants me to filter on a CommitAuthor for history(author: ). I tried passing my username, or my unique user ID, but it doesn't work. I am essentially passing it a string, but it wants the type CommitAuthor. How do I pass a CommitAuthor value?
It isn't clear to me, and I searched through the docs and the schema and I couldn't find anything.
Please help!
Ah, so the answer is actually very simple once I looked at the graphql documentation (rather than just the github documentation). CommitAuthor is an input type, which is described here https://graphql.org/graphql-js/mutations-and-input-types/.
The result is you pass an object of CommitAuthor. In this case I just have to pass the id, which looks like this: author: {id: "MDQ6VXNlcjIyNDE3Mzgy"}
See the completed code below.
{
user(login: "davekaj") {
id
repositories(first: 10, orderBy: {field: NAME, direction: ASC}) {
nodes {
ref(qualifiedName: "master") {
target {
... on Commit {
history(first: 15, author: {id: "MDQ6VXNlcjIyNDE3Mzgy"}) {
totalCount
nodes {
additions
author {
name
user {
id
}
}
committedDate
deletions
}
}
}
}
}
}
}
}
}

Get other related records (with id different that queried)

As a newbie to GraphQL I would appreciate some help in the following:
I have query which retrieves its author and that author's books. I would like the author's books to be author's other books, meaning - except the one being queried. What does it involve?
apollo-angular query:
const getBookQuery = gql`
query($id: ID){
book(id: $id){
id
name
year
author {
id
firstName
lastName
books { # <-- give me all _except_ the one with $id
name
year
id
}
}
}
}
`;
and in the schema.js (node.js server) I have something like:
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
book: {
type: BookType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
const { id } = args;
return Book.findById(id);
},
},
books: {
type: GraphQLList(BookType),
resolve() {
return Book.find({});
},
},
// ... other queries ...
}
})
The solution I am looking for should, obviously, not break other queries for books.
You should be able to achieve the exclusion by adding an argument to the Author type def and then appropriately using that argument in the resolver for books (which should be nested resolver on your Author type). Will need to adapt syntax for apollo-angular.
type Author {
id:
firstName: String
lastName: String
books(exclude: ID): [Book]
}
const resolverMap = {
Query: {
book(arent, args, ctx, info) {
...
}
},
Author: {
books(obj, args, ctx, info) {
// Use args.exclude passed to filter results
},
},
};
const getBookQuery = gql`
query($id: ID){
book(id: $id){
id
name
year
author {
id
firstName
lastName
books(exclude: $id) {
name
year
id
}
}
}
}
`;

Is it possible to fetch data from multiple tables using GraphQLList

In GraphQL we can write the object type in GraphQLList and fetch all the fields. I am using Association and it is joining the two tables but I am unable to fetch the field of both the tables. It only takes the fields what I have written in GraphQLList.As I want the list of data.
Here is the code
films table:
module.exports =(sequelize, DataTypes) => {
const films = sequelize.define(
'films',
{
id:{
type: DataTypes.INTEGER,
primaryKey: true,
allowNull: false,
},
name: {
type: DataTypes.STRING,
},
},
);
films.associate = (models) => {
films.hasMany(models.movie_stream, {
foreignKey: 'movie_id',
});
};
return films;
}
movie_stream table:
module.exports = (sequelize, DataTypes) => {
const movie_streams = sequelize.define('movie_streams', {
id:{
type: DataTypes.INTEGER,
primaryKey: true,
allowNull: false,
},
movie_id: {
type: DataTypes.STRING,
foreignKey: "movie_id",
},
});
movie_streams.associate = (models) => {
movie_streams.hasMany(models.films, {
foreignKey: 'id',
});
};
return movie_streams;
};
Schema file:
movieList:{
type: new GraphQLList(Films),
resolve: (parent,args)=>{
return newdb.films.findAll({attributes:['id','name','permalink'],
where: {content_category_value:parent.id },
include: [{
model:newdb.movie_stream,
attributes:['id','movie_id'],
}],
}).then(data=>{
return data;
})
}
Can I write here type: new GraphQLList(Films, MovieStream)??
I have tried but It does not work. Please give me some idea how do I fetch the fields of both the table???
There's two main ways of achieving this in GraphQL: unions and interfaces.
An interface is where two or more object types in your GraphQL schema share certain fields (characteristics). For example you might have a Product interface for all the items in your shop, where every product has a price, barcode, and shelfLocation. All your products, such as Shampoo, Bread, LawnChair would then implement this interface.
interface Product {
price: Float
barcode: Int
shelfLocation: ShelfLocation
}
type Bread implements Product {
price: Float
barcode: Int
shelfLocation: ShelfLocation
brand: String
numberOfSlices: Int
calories: Float
bestBefore: Date
}
extend type Query {
searchProducts(phrase: String!): [Product!]
}
A union is where you declare that something can return more than one object type, but those types don't have to have any properties in common.
type Shark {
name: String
numberOfTeeth: Int
}
type Shoe {
brand: String
size: String
}
union SharkOrShoe = Shark | Shoe
extend type Query {
searchSharksAndShoes(phrase: String!): [SharkOrShoe!]
}
In both cases you can query type specific fields using fragments or inline fragments:
query {
searchProducts(phrase: "tasty") {
# shared fields
__typename
price
barcode
shelfLocation { aisle, position }
# type specific fields
... on Bread { brand }
...breadFrag
}
searchSharksAndShoes(phrase: "sleek") {
# only the introspection fields are shared in a union
__typename
# type specific fields
... on Shark { name, numberOfTeeth }
...shoeFrag
}
}
fragment breadFrag on Bread {
barcode
bestBefore
}
fragment shoeFrag on Shoe {
brand
size
}
You can learn more about this in the GraphQL schema documentation and read about GraphQLInterfaceType and GraphQLUnionType in the GraphQL.js documentation.

Write resolvers for nested type definitions

Suppose I have following type definition for my GraphQL API:
const typeDef = `
type Book {
title: String
author: Author
likes: Int
}
type Author {
id: String
name: String
age: Int
books: [Book]
}
type Query{
books(authorid: String!): Book
}
`
Then, how many resolvers do I need for this? Should I handle this query request with only one resolver books and return all books and author info or should I make many resolvers such as Query -> books, Book -> author and Author -> books? I am not sure how the modular schema and resolver works together.
No matter how many type(Book, Author etc) or input you use you need to provide .
const schema = `
type Mutation {
mutatePost(postId:Int) :Int
}
type Query {
hello: String
posts: [String]
books(authorId: String!): Book
}
`
You need to use same name as you defined in Query must be same in resolver
const resolvers = {
Query: {
async hello() {
return 'Hello';
},
async posts() {
return ['Hello', 'World];
},
async books(_, { authorId }) {
//Return data which you is defined in type Book
//return Book
}
},
Mutation: {
async mutatePost(_, {
postId
}, context) {
//return Integer
}
},
}
Only thing every Query and Mutation need queryResolver and mutationResolver

How to write graphql query wiith custom objects

The server side of graphql is with nodejs and express. This is the schema for graphql. It has one query which accepts DateT object having from and to dates.
var schema = buildSchema(`
type Query {
courseWithDate(
timeFilter: DateT
): Course
},
type Course {
...
from: String
to: String
},
type DateT{
from : String
to : String
}
`);
and this is how I am getting courses
I am able to run the application with this url
localhost:4000/graphql
This is the query I am using
query courseWithDate($from: dateFrom, $to: dateTo) {
courseWithDate(timeFilter: {
from: "${dateFrom}"
to: "${dateTo}"
}) {
title
...
}
}
with these parameters
{
"from": "2019-10-10","to":"2019-10-10"
}
Exception message I get is related to the input type I am trying to pass.
{
"errors": [
{
"message": "The type of Query.courseWithDate(timeFilter:) must be Input Type but got: DateT.",
"locations": [
{
"line": 6,
"column": 25
}
]
}
]
}
I'm not sure, but probably this style looks more like best practice
type Course {
id: Int
title: String
author: String
from: String
to: String
description: String
topic: String
url: String
}
input DateInput {
dateFrom: String!
dateTo: String!
}
type Query {
courseWithDate(input: DateInput!, name: String!): Course
}
And Query on client side should be:
{
courseWithDate(input: {
dateFrom: "${dateFrom}"
dateTo: "${dateTo}"
}
name: "${name}")
{
id
name
}
}

Resources