Can we pass dynamic schema details in GraphQL query which can be used by JoinMonster? - graphql

I'm not sure if passing the schema name as an argument in the GraphQL query will work for JoinMonster or not. Following is the query example:
{
configuration_queries(table: 'xyz', where: 'some condition') {
data {
col1
col2
}
}
}
so here it is expected to create a dynamic query on "xyz" table using JoinMonster.

Yes, it's possible to pass schema details dynamically to GraphQL queries. There are a few different ways to do this, but one approach would be to use the graphql-tools package:
Install the graphql-tools package:
npm install --save graphql-tools
Write your GraphQL query, using the graphql-tools syntax for dynamic schema details:
const query = `
query($schema: String!) {
joinMonster(sql: $schema)
}
`;
Call the graphql function, passing in your query and dynamic schema details:
const schemaDetails = `
SELECT * FROM users
JOIN posts ON users.id = posts.user_id
`;
graphql(query, { schema: schemaDetails })
.then((result) => {
// handle results...
})
.catch((error) => {
// handle errors...
});

Related

Creating dynamic graphql query using apollo/client

I am trying to create a graphql query where the query data type and filter parameters will be passed dynamically based on user input.
I have written the below query which filters using only one field shipdate.
const GET_SHIPDATA_WITH_FILTER = gql`
query GetShipData($shipdateStart: timestamptz, $shipdateEnd: timestamptz, $limit: Int) {
shipdata(where: {shipdate: { _gte: $shipdateStart, _lte: $shipdateEnd}},limit: $limit) {
status
import_time
shipdate
}
}
`;
const variables = {
shipdateStart: "some date",
shipdateEnd: "some date",
limit: 50,
};
If no filter is passed I'm using this one
const GET_SHIPDATA = gql`
query GetShipData($limit: Int) {
shipdata(limit: $limit) {
status
import_time
shipdate
}
}
`;
const variables = {
limit: 50,
};
You can see I have written two queries to handle two types of filters which won't work if I want to add more filters.
Now I am trying to write a single dynamic query where if the user wants to add more filters like status: {_eq: $status} or import_time: { _gt: $importTimeStart, _lt: $importTimeEnd} then I will pass the variables and the query will dynamically handle the filters. Something like
const GET_SHIPDATA = gql`
query GetShipData($allfilters: AllFilterTypes) {
shipdata(filter: $allfilters) {
status
import_time
shipdate
}
}
`;
const variables = {
//pass allFilters based on user input,
};
Btw I'm using react and hasura if it helps anyway.
Hasura already exposes types in your GraphQL schema that refer to "filter conditions". In Hasura, they're called Bool_Exp (short for boolean expression) and they map directly to the where clause.
If you just update your query to receive a shipdata_bool_exp you'll be able to build up a dynamic filter expression in your application code and it will work as expected.
const GET_SHIPDATA_WITH_FILTER = gql`
query GetShipData($filter: shipdata_bool_exp!) {
shipdata(where: $filter,limit: $limit) {
status
import_time
shipdate
}
}
`;

using a single query to call multiple queries using apollo react hooks

I am new to this graphql, so what i am trying to achieve here is, i need to call two queries parallelly basically combining the queries and get the loading at a single time.
here i have seperated the queries and using two loading state, i need to combine it like compose.
The use case is, user clicks on the button on the button click i will pass the id, and hit both queries and get the list of data
<Button
text="Details"
onClick={() => {
getNames({ variables: { location_id: Number(location_id) } });
getSchools({ variables: { location_id: Number(location_id) } });
}}
>
const [getNames, { loading: namesLoading, data: namesData }] = useLazyQuery(
GET_NAMES
);
const [
getSchools,
{ loading: schoolsLoading, data: schoolsData },
] = useLazyQuery(GET_SCHOOLS);
const GET_NAMES = gql`
query get_names($location_id: Int!) {
get_names(location_id: $location_id) {
id
name
}
}
`;
const GET_SCHOOLS = gql`
query get_schools($location_id: Int!) {
get_schools(location_id: $location_id) {
schools {
id
name
}
}
}
`;
With splitting i am able to see the data, i am using "#apollo/react-hooks" to get the data with useLazyQuery, how can i achieve with this a single query. So instead of multiple loading , error data i can have a single one
Didn't find any compose hook from this library

How can i search by field of joined table in graphql and nestjs

i create two table tag and tagTranslation.
following is field of each
Tag
id, type, transloations, creaed_at, updated_at
TagTranslation
id, tag_id, name, language
I use graphql, i want to get tag list by type, name and language
{ tags(name:"tag1", language:"en, type:3){
id,
type,
translations{
id,
name,
language,
}
}
}
so I create resolver like following
#Query(returns => [Tag])
tags(#Args() tagArgs: TagArgs): Promise<Tag[]> {
const where = {
...(tagArgs.type) && {type: tagArgs.type}
};
const include_where = {
...(tagArgs.name) && {name: { [Op.like]: `%${tagArgs.name}%` }},
...(tagArgs.language) && {language: tagArgs.language}
};
return this.tagService.findAll({
where: where,
include: {
as: 'translations',
model: TagTranslation,
where: include_where,
required: true,
}
});
}
#Query(returns => Tag)
tag(#Args({name: 'id', type: ()=> Int}) id: number): Promise<Tag>{
return this.tagService.get(id)
}
#ResolveProperty()
async translations(#Parent() tag): Promise<TagTranslation[]>{
const { id } = tag;
return await this.tagTranslationService.findAll({tag_id: id});
}
when i call tags, the query is called twice
first, A query is executed to get the results I want.
but second,
SELECT `id`, `tag_id`, `name`, `language`, `created_at`, `updated_at` FROM `tag_translation` AS `TagTranslation` WHERE `TagTranslation`.`tag_id` = 1;
query is called once more, so i can't get results what i want.
I think second query is called because of ResolveProperty, I remove ResolveProperty. after that, tag query is not include tagtranslation info...
how can i solve that problem ? or is there another idea??
how can i solve that problem ? or is there another idea??
Relations between entities should be resolved on a field resolver (#ResolveProperty()) level because when someone requests only id and type, you will still perform additional, not needed join on TagTranslation in sql query.

Optional queries in Gatsby / GraphQL

I have a Gatsby site with a contentful source, the initial page build GraphQL looks like this:
{
allContentfulProduct {
edges {
node {
slug
contentfulid
}
}
}
}
this works fine when using the preview API, but when using the production one it fails unless I have at least 1 Product entry published:
There was an error in your GraphQL query:
Cannot query field "allContentfulProduct" on type "Query". Did you mean ... [suggested entry names] ?
I'm pretty sure that when I publish a Product things will work as expected, but is there any way to make this query optional. The query should return zero results, and thus no Product pages will be created (expected outcome if no Product entries are published)
Try to add into your gatsby-node.js file and play around that.
exports.createSchemaCustomization = ({ actions }) => {
const { createTypes } = actions
const typeDefs = `
type allContentfulProduct implements Node{
slug: String,
contentfulid: String
}`

GraphQL add introspection from a variable

I want to add introspection from a variable to my app.
I have this kind of introspection:
{"data":{"__schema":{"queryType":{"name":"PageContentQuery"}....
(that im getting from rest request)
I want this variable to be the schema provider, is it possible?
The full variable is here: https://stackblitz.com/edit/ts-graphql-demo-ypgi18?file=index.tsx
const fetcher = (params: any) => {
console.log(params);
return graphql(schema, params.query, params.variables);
}
const defaultQuery = `{
page{id,contents}
}`;
render(
<GraphiQL fetcher={fetcher} schema={schema} defaultQuery={defaultQuery}/>,
document.getElementById('root'),
);
thanks
Given the results of an introspection query, you can build a schema using buildClientSchema:
import { buildClientSchema } from 'graphql'
const schema = buildClientSchema(introspectionResult)
You can then pass that schema as prop to the GraphiQL component:
<GraphiQL fetcher={fetcher} schema={schema} />
Of course, that's generally not necessary -- if the schema is not passed in, then GraphiQL will just make an introspection query for you using the fetcher you provide.

Resources