2
votes

What is the approach when your subquery needs some field from parent to resolve?

In my case owner_id field from parent is needed for owner resolver, but what should i do if user will not request it?

Should i somehow force fetch owner_id field or skip fetching owner when owner_id is not in request?

Problematic query:

 project(projectId: $projectId) {
      name
      owner_id <--- what if user didn't fetch this
      owner {
        nickname
      }
    }

Graphql type:

  type Project {
    id: ID!
    name: String!
    owner_id: String!
    owner: User!
  }

And resolvers:

export const project = async (_, args, ___, info) => {
  return await getProjectById(args.projectId, getAstFields(info))
}

export default {
  async owner(parent, __, ___, info) {
    return await getUserById(parent.owner_id, getAstFields(info))
  },
}

Helper functions that doesn't matter:

export const getUserById = async (userId: string, fields: string[]) => {
  const [owner] = await query<any>(`SELECT ${fields.join()} FROM users WHERE id=$1;`, [userId])

  return owner
}

export const getAstFields = (info: GraphQLResolveInfo): string[] => {
  const { fields } = simplify(parse(info) as any, info.returnType) as { fields: { [key: string]: { name: string } } }

  return Object.entries(fields).map(([, v]) => v.name)
}
1
always read owner_id? attach it to getAstFields() resultxadm
@xadm getAstFields is function that get requested fields for sql query, i'm not sure what do you mean...ZiiMakc
modify it to accept additional parameter, always return owner_id (in subset) even if not defined/requested in queryxadm
@xadm thanks, i was thinking that resolver will drop additional props internally. Please answer so i could accept it.ZiiMakc

1 Answers

2
votes

You can always read owner_id in project type resolver.

In this case ... modify getAstFields function to accept additional parameter, f.e. an array of always required properties. This way you can attach owner_id to fields requested in query (defined in info).

I was thinking that resolver will drop additional props internally.

It will be removed later, from 'final' response [object/tree].