Apollo GraphQL: Can One Query Support Lookup Different Lookup Fields? - graphql

I've got a working query that looks like this:
const GETONEASSOCIATE_QUERY = gql`
query getOneAssociate($_id: String!) {
getOneAssociate(_id: $_id) {
_id
first_name
last_name
city
state
userIDinRelatedTable
}
} `;
Now I'd like to be able to look up an associate by userIDinRelatedTable. Do I have to write a whole new graphQL query, or, is there a way to set up a query so that I can specify what fields to be used for the lookup -- something like:
enter code herequery getOneAssociate($_args: args) {
Thanks in advance to all for any thoughts/advice/info!

I'm guessing in your scheme you have a userIDinRelatedTable field on Associate which resolves to RelatedTable.
So to get the fields returned in your query you can
const GETONEASSOCIATE_QUERY = gql`
query getOneAssociate($_id: String!) {
getOneAssociate(_id: $_id) {
_id
first_name
last_name
city
state
userIDinRelatedTable {
id
field1
field2
}
}
} `;

Related

GraphQL using a dynamic ID from set of returned results to render correct set of data

I am pretty new to graphql, so my question might sound a bit strange. it may not be correct way of doing what I need, but I can't think of any other way.
Basically, I would like to know how I can use an ID i am being returned from my graphql query and use that ID in the second query to render the data I need.
currently my full query looks like:
export const query = graphql`
query myQuery {
allSanityFrontpage {
nodes {
content {
... on SanityHero {
_key
_type
heroIntro
heroHeader
heroButtonText
heroProjectReference {
id
title
slug {
current
}
}
}
}
}
}
sanityProject(id: { eq: "-8571b76b-8cfd-55cf-b848-151586f5c57a" }) {
id
title
coverImage {
asset {
title
fluid(maxWidth: 800) {
...GatsbySanityImageFluid
}
}
}
}
}
`;
I am getting an ID returned from this part of the query
heroProjectReference {
id
And currently I am using that ID statically to render the content I need by doing this:
sanityProject(id: { eq: "-8571b76b-8cfd-55cf-b848-151586f5c57a" }) {
id
title
How do I replace that static ID with something dynamic, so I can update my CMS and see whatever project I have updated it to be?
Client-side you must call the chained queries serially, populating the ID in the dependent query with the output from the first query.
Server-side, of course, you can combine the two in the resolver.

How to create/Fetch data dynamically by filters and order in GraphQL?

I am creating a query in graphql + apollo client whose filters and orders can change depending on what the customer selects in the frontend. For example:
query (
$orderPart: String!
$wherePart: String!
) {
getProductInfo(
order {$orderPart}
where {$wherePart}
) {
productID
description
size
model
cathegoryNumber
}
Where $orderPart will be equal to "description: DESC" or "productID: ASC" (depending what the customer selected in a momento or another). And $wherePart will be equal to "cathegoryNumber: {eq: 12}" or "productID: {eq: 111111}".
I need to pass the order/filter clause completely as a parameter.
But it doesn't work. Syntax is error "Syntax Error: Expected name, found $".
So my question is...
Is there any way to implement these dynamic filters/orders? How could this functionality be implemented? Is there any other way to implement this dynamic filters and orders?
Thanks.
Note:
In the official documentation, I found that only values can be passed as a parameters:
query (
$orderValue: sortEnumType! = DESC
$whereValue: String! = "description1"
) {
getProductInfo(
order {productID: $orderValue}
where {description: {eq: $whereValue} }
) {
productID
description
size
model
cathegoryNumber
}
But that is not what I need because always filters/orders couldn't be changed. And they could be completely different each time (prodyuct:ASC) first time, (cathegoryNumber:DESC) second time, etc...
Thanks for your help, I found a solution. Using apollo client and variables when the template is created:
let orderValue = 'order {productID: ASC}'; // built dynamically
let whereValue = 'description: {eq: "description1"}'; // built dynamically
document = gql`
query {
getProductInfo(
${orderValue}
${whereValue}
) {
productID
description
size
model
categoryNumber
}
`;

How to find path to a field in a graphql query

I am very new to graphql. I have a following graphql query for an example:
query pets {
breed(some arguments)
{
name
items
{
owner(some arguments)
{
items
{
ID
ownerSnumber
country
address
school
nationality
gender
activity
}
}
name
phoneNumber
sin
}
}
}
Is it possible to parse a gql query and get the path of a field in the query?
For example I would like to get the path of 'ID'. For example from the above query, is it possible to get the path where the ID is: owner.items.ID
With https://graphql.org/graphql-js/ it exposes a fourth argument called resolve info. This field contains more information about the field.
Have a look at GraphQLObjectType config parameter type definition:
With a good start from the earlier answer, relying on the ResolveInfo you could do something like a recursive check going from child to parent:
export const getFieldPath = (path: Path): string => {
if (!path.prev) return `${path.key}`
return `${getFieldPath(path.prev)}.${path.key}`
}
And later in your resolver you could use it like:
const myFieldResolver = (parent, args, ctx, info) => {
const pathOfThisResolversField = getFieldPath(info.path)
// use your pathOfThisResolversField
return yourFieldResolvedData
};
Worth noting though, the solution above will include every node all the way to the query root, rather than just the ones you mentioned owner.items.ID

Return custom field based on other not requested field?

Let's say that I want to get a person's age using this query:
{
getUser(id: "09d14db4-be1a-49d4-a0bd-6b46cc1ceabb") {
full_name
age
}
}
I resolve my getUser query like this (I use node.js, type-graphql and knex):
async getUser(getUserArgs: GetUserArgs, fields: UserFields[]): Promise<User> {
// Return ONLY ASKED FIELDS
const response = await knex.select(this.getKnexFields(fields)).from(USER).whereRaw('id = ?', [getUserArgs.id]);
// returns { full_name: 'John Smith' }
return response[0];
}
The problem is that then I can't calculate age field, because I did not get born_at (datetime field stored in a db) in the first place:
#FieldResolver()
age(#Root() user: User, #Info() info: GraphQLResolveInfo): number {
console.log(user); // { full_name: 'John Smith' } no born_at field - no age, so error
// calculate age from born_at
return DateTime.fromJSDate(user.born_at).diff(DateTime.fromJSDate(new Date()), ['years']).years;
}
Is there some fancy graphql-build-in way / convention to predict that born_at will be needed instead of doing it manually through info / context?
You should always return full entity data from the query-level resolvers, so they are available for field resolvers.
The other solution is to manually maintain a list of required fields for field resolvers, so your "fields to knex" layer can always include them additionally".
Further improvements might be to can a list of additional columns based on the requested fields (thus the field resolvers that will be triggered).

Dynamically pass required fields into GraphQL query

I have a query where my required fields inside the query may change. User is allowed to generate the query on fly and user can select the fields in the query. Is there a way to pass the required fields into query based on user's selection from a dropdown. Eg: in below query id, traveller, visaApplication can be replaced by anyother fields. So my queries has to dynamic.
{
Travels{
id
traveller {
nationality
firstName
}
visaApplication {
nationality
city
}
}
}
Fields can be added dynamically using string interpolation:
const otherFields = `
traveller {
nationality
firstName
}
`
const query = gql`
{
Travels {
id
${otherFields}
}
}
`
You can also utilize the #skip or #include directives, combined with variables, to control whether to skip/include particular fields for a specific request while utilizing a single query:
const query = gql`
query (
$includeTraveller: Boolean!
$includeVisa: Boolean!
) {
Travels {
id
traveller #include(if: $includeTraveller) {
nationality
firstName
}
visaApplication #include(if: $includeVisa) {
nationality
city
}
}
}
`

Resources