How to make a foreach request in Apollo GraphQL? - graphql

I have a blog in javascript and I'm using Apollo GraphQL to save my data. I intend to make a list with six posts of all categories. Like this:
[
technology: [
post1,
post2,
...
],
cook: [
post1,
post2,
...
],
...
]
But I couldn't. I thought in take all categories's id's and make a big request, like this:
{
firstCategory: allPosts(where: {category: "firstId"}, first: 6) {
...fields
}
secondCategory: allPosts(where: {category: "secondId"}, first: 6) {
...fields
}
}
But if I add a new category, I must change my code.

You can pass categories [queried earlier] as variables, like:
query posts($firstCat: String, $secondCat: String, $limit: Int) {
firstCategory: allPosts(where: {category: $firstCat}, first: $limit) {
...fields
}
secondCategory: allPosts(where: {category: $secondCat}, first: $limit) {
...fields
}
}
variables:
{
"firstCat": "technology",
"secondCat": "cook",
"limit": 6
}
Of course, it's still limited to n prepared aliases.
Building dynamic aliases are possible but not adviced - source ... AST tools should be used as gluing strigs (directly or using literals) is considered as abusing GraphQL.
You can also destructure this component, multiple <Category name="technology" /> components with their own internal query (use props.name as category filter variable). This will make separate requests.
For speed and SEO purposes you can use gatsby (amount of separate requests doesn't matter ... up to some scale) - but (as all static generators) it requires rebuild/redeploy on changes.
Good API should let you query for tags and related posts inside each of them (sorted by any criteria; ... and author inside [and his posts] ... etc - it's a standard GraphQL feature).

Related

How to insert many mutations in a single GraphQL request?

I using https://hygraph.com/, and I want insert (create many products) in a single GraphQL request.
At the moment I know how to insert one product:
mutation {
createProduct(data: { title: "Face Mask", slug: "dfavce-mask", price: 1000 }) {
id
}
}
I read the documentation, but I didn't see information about bulk creation records.
Link for hygraph documentation:
https://hygraph.com/docs/api-reference/content-api/mutations#create-entries
The top-level query you show is just a query against the Mutation type (or another type specified in the schema). Like any other query, it can have multiple fields. At a technical level, the only special thing about GraphQL mutations is that, if you do have multiple fields, they execute sequentially.
Also like other queries, if you want to request the same field multiple times (run similarly-named mutations) you need to use an alias to disambiguate the results.
mutation {
createFaceMask: createProduct(data: { title: "Face Mask" }) { id }
createHandSanitizer: createProduct(data: { title: "Hand Sanitizer" }) { id }
}

Can I create two different graphql query for two different folders separately in my Gatsby project

I'm a newbie programmer and Recently I want to add a blog page to my website. I already have a projects page using Graphql and .md files, now my problem is, every time I try to create a blog post with .md, it appears also in my projects page, could you please advice me with some of your kind experience on solving this issue and do I have to create a separate query? even I don't know how?
this is my current query.
export const query = graphql`
query ProjectsPage {
allMarkdownRemark(sort: { fields: frontmatter___date, order: DESC }) {
nodes {
frontmatter {
slug
stack
title
thumb {
childImageSharp {
gatsbyImageData(placeholder: BLURRED, layout: FULL_WIDTH)
}
}
}
id
}
}
}
One easy thing you can do is to add a key field on your markdown files to distinguish between posts and projects. This will allow you to filter GraphQL queries. In the same way, you can also place the markdowns in separate folders and filter them using the relative/absolute path.
export const query = graphql`
query ProjectsPage {
allMarkdownRemark(filter: { frontmatter: {key: { eq: "project" }}, sort: { fields: frontmatter___date, order: DESC }) {
nodes {
frontmatter {
slug
stack
title
thumb {
childImageSharp {
gatsbyImageData(placeholder: BLURRED, layout: FULL_WIDTH)
}
}
}
id
}
}
}
As I said, this approach assumes that you have created a key: project field in your markdown files. You can do the same using key: article.
Alternatively, placing the markdowns in different folders using fileAbsolutePath/relativePath if needed in the same way. This approach will rely on your filesystem structure to determine the available paths. Both approaches are based on a filtered query, choose whatever suits you better.
Use the GraphiQL playground to test all queries, paths and filters at localhost:8000/___graphql

Typed document node with vue3 apollo and complex where

I use this package https://github.com/dotansimha/graphql-typed-document-node and I usually call it like this useQuery(peopleDocument, variables).
But laravel lighthouse has a complex where plugin which automatically adds all types for various queries where conditions for example
{ people(where: { column: AGE, operator: EQ, value: 42 }) { name } }
I would like to allow users to build their own filters with their own operators but how I can define such query when filters and their operators are dynamic?
#xadm vague explanation somehow helped. So I'll answer my own question.
I'm unsure if it's how to should be used but it does work.
Lighthouse generates operators and columns enums automatically with #whereConditions directive. So you have to run yarn graphql-codegen again to fetch them.
And then simply import then simply use them in component
Lighthouse schema definition example:
type Query {
contact(where: _ #whereConditions(columns: ["id", "email", "mobile"])): Contact #first
}
Query definition:
query contact($where: QueryContactWhereWhereConditions) {
contact(where: $where) {
id
email
mobile
}
}
Vue component:
import { ContactDocument, QueryContactWhereColumn, SqlOperator } from 'src/typed-document-nodes.ts';
useQuery(ContactDocument, {where: {column: QueryContactWhereColumn.Email, operator: SqlOperator.Like, value: '%#example.com'}})

how to get the Graphql request body in apollo-server [duplicate]

I have written a GraphQL query which like the one below:
{
posts {
author {
comments
}
comments
}
}
I want to know how can I get the details about the requested child fields inside the posts resolver.
I want to do it to avoid nested calls of resolvers. I am using ApolloServer's DataSource API.
I can change the API server to get all the data at once.
I am using ApolloServer 2.0 and any other ways of avoiding nested calls are also welcome.
You'll need to parse the info object that's passed to the resolver as its fourth parameter. This is the type for the object:
type GraphQLResolveInfo = {
fieldName: string,
fieldNodes: Array<Field>,
returnType: GraphQLOutputType,
parentType: GraphQLCompositeType,
schema: GraphQLSchema,
fragments: { [fragmentName: string]: FragmentDefinition },
rootValue: any,
operation: OperationDefinition,
variableValues: { [variableName: string]: any },
}
You could transverse the AST of the field yourself, but you're probably better off using an existing library. I'd recommend graphql-parse-resolve-info. There's a number of other libraries out there, but graphql-parse-resolve-info is a pretty complete solution and is actually used under the hood by postgraphile. Example usage:
posts: (parent, args, context, info) => {
const parsedResolveInfo = parseResolveInfo(info)
console.log(parsedResolveInfo)
}
This will log an object along these lines:
{
alias: 'posts',
name: 'posts',
args: {},
fieldsByTypeName: {
Post: {
author: {
alias: 'author',
name: 'author',
args: {},
fieldsByTypeName: ...
}
comments: {
alias: 'comments',
name: 'comments',
args: {},
fieldsByTypeName: ...
}
}
}
}
You can walk through the resulting object and construct your SQL query (or set of API requests, or whatever) accordingly.
Here, are couple main points that you can use to optimize your queries for performance.
In your example there would be great help to use
https://github.com/facebook/dataloader. If you load comments in your
resolvers through data loader you will ensure that these are called
just once. This will reduce the number of calls to database
significantly as in your query is demonstrated N+1 problem.
I am not sure what exact information you need to obtain in posts
ahead of time, but if you know the post ids you can consider to do a
"look ahead" by passing already known ids into comments. This will
ensure that you do not need to wait for posts and you will avoid
graphql tree calls and you can do resolution of comments without
waiting for posts. This is great article for optimizing GraphQL
waterfall requests and might you give good idea how to optimize your
queries with data loader and do look ahead
https://blog.apollographql.com/optimizing-your-graphql-request-waterfalls-7c3f3360b051

GraphQL query based on a specific value of a field

I want to be able to retrieve the latest release from GitHub for a specific repo using their GraphQL API. To do that, I need to get the latest release where isDraft and isPrerelease are false. I have managed to get the first part, but cant figure out how to do the "where" part of the query.
Here is the basic query I have gotten (https://developer.github.com/v4/explorer/):
{
repository(owner: "paolosalvatori", name: "ServiceBusExplorer") {
releases(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) {
nodes {
name
tagName
resourcePath
isDraft
isPrerelease
}
}
}
}
Which returns:
{
"data": {
"repository": {
"releases": {
"nodes": [
{
"name": "3.0.4",
"tagName": "3.0.4",
"resourcePath": "/paolosalvatori/ServiceBusExplorer/releases/tag/3.0.4",
"isDraft": false,
"isPrerelease": false
}
]
}
}
}
}
I cant seem to find a way to do this. Part of the reason is that I am new to GraphQL (first time trying to do a query) and I am not sure how to frame my question.
Can one only "query" based on those types that support arguments (like repository and releases below)? Seems like there should be a way to specify a filter on the field values.
Repository: https://developer.github.com/v4/object/repository/
Releases: https://developer.github.com/v4/object/releaseconnection/
Node: https://developer.github.com/v4/object/release/
Can one only "query" based on those types that support arguments
Yes: GraphQL doesn't define a generic query language in the same way, say, SQL does. You can't sort or filter a field result in ways that aren't provided by the server and the application schema.
I want to be able to retrieve the latest [non-draft, non-prerelease] release from GitHub for a specific repo using their GraphQl API.
As you've already found, the releases field on the Repository type doesn't have an option to sort or filter on these fields. Instead, you can iterate through the releases one at a time with multiple GraphQL calls. These would individually look like
query NextRelease($owner: String!, $name: String!, $after: String) {
repository(owner: $owner, name: $name) {
releases(first: 1,
orderBy: {field: CREATED_AT, direction: DESC},
after: $after) {
pageInfo { lastCursor }
nodes { ... ReleaseData } # from the question
}
}
}
Run this in the same way you're running it now (I've split out the information identifying the repository into separate GraphQL variables). You can leave off the after variable for the first call. If (as in your example) it returns "isDraft": false, "isPrerelease": false, you're set. If not, you need to try again: take the value from the lastCursor in the response, and run the same query, passing that cursor value as the after variable value.
{
repository(owner: "paolosalvatori", name: "ServiceBusExplorer") {
releases(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) {
nodes(isDraft :false , isPrerelease :false ) {
name
tagName
resourcePath
isDraft
isPrerelease
}
}
}
}
Alternatively please have look at GraphQL directives, as sometimes it's required to skip or include the fields on the basis of the values
#skip or #include.
The skip directive, when used on fields or fragments, allows us to exclude fields based on some condition.
The include directive, allows us to include fields based on some condition
GraphQL Directives

Resources