Reputation: 6814
I am figuring my way around creating a GraphQL API using MongoDB and I am trying to get my head around interfaces.
I get the idea behind it and watched a bunch of videos on talks and howto's, but the one thing I am seeing is how to make the query resolver.
It is always displayed like this: groups: () => { ... }
groups
would be listed in the query type, so it would need the mongodb query.
This is the resolver that I need to find the answer for:
What goes inside of the {...}
?
Query: {
groups: () => { ... },
families: () => Family.find(),
members: () => Member.find(),
},
I think the area I am stuck in when it comes to the query is that: "What would the query be since groups
is not a mongodb document?"
MORE INFORMATION:
Here is the full typedef
export const typeDefs = gql`
interface Group {
id: ID!
name: String!
}
type Family implements Group {
id: ID!
name: String! # persons family name
numberOfPeople: Int
}
type Member implements Group {
id: ID!
name: String! # persons first name
age: Int!
}
type Query {
groups: [Group]
families: [Family]
members: [Member]
}
}
Here is the resolver
export const resolvers = {
Group: {
__resolveType(group, context, info){
if(group.family){
return 'Family';
}
if(group.member){
return 'Member';
}
return null;
},
},
Query: {
groups: () => { ... },
families: () => Family.find(),
members: () => Member.find(),
}
}
The idea is that Family
and Member
are separate documents which hold the data and that Group
is the interface to create a query that combines them.
Upvotes: 1
Views: 358
Reputation: 6814
For anyone who comes to this question - this is the code I had to put inside of the Query{ ... }
Effectively it is the function that executes the database query.
Groups
is for a plural return,
Group
is for a singular return
groups: async () => {
let types = mongoose.modelNames()
let total = []
for(let t of types) {
let temp = await mongoose.model(t).find()
total.push(temp)
}
let flat = total.flat()
return flat
},
group: (_, { id }) => {
return mongoose.modelNames().map(async mn => {
if (await mongoose.model(mn).exists({"_id": ObjectID(id)})) {
return mongoose.model(mn).findOne({"_id": ObjectID(id)})
}
})
},
Upvotes: 0
Reputation: 424
edit: I re-readed your post and what you are trying to access here may not exist.
Because at the __resolveType
you are validating against a schema property.
// Group:
{
__resolveType(group, context, info){
if(group.family){ // property family is not defined in a group implementation.
return 'Family';
}
if(group.member){
return 'Member';
}
return null;
},
},
You may want to perform a validation against a defined unique property from an implementation either Family or Member like follows:
// Group:
{
__resolveType(group, context, info){
if(group.numberOfPeople){
return 'Family';
}
if(group.age){
return 'Member';
}
return null;
},
},
Then when you query groups.
`
{
groups {
id
name
... on Family {
numberOfPeople
}
... on Member {
age
}
}
}
`
I have found the best way to get typings for TS automatically from your schema using graphql-code-generator. It has also a plugin to get automatically generated mongoDB models
For a quick response paste your schema here.
Quick setup for typescript:
npm i -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-resolvers
It will install cli and typescript + typescript-resolvers plugins.
codegen.yml
and put:overwrite: true
schema: 'http://localhost:3500/graphql'
generates:
src/utils/codegen/graphql.ts:
plugins:
- 'typescript'
- 'typescript-resolvers'
graphql-codegen --config codegen.yml --watch src/**/*.ts
// Import the types of your generated ts file.
import { MutationResolvers, QueryResolvers, Resolvers } from '@/utils/codegen/graphql'
const Query: QueryResolvers = {
players: () => players
}
const Mutation: MutationResolvers = {
updatePlayer: () => player
}
const resolvers: Resolvers = {
Query,
Mutation
};
export default resolvers;
Screenshot examples:
Upvotes: 1