graphql, split huge query to small queries - graphql

I am using https://developer.github.com/v4/
And I have a huge query like this:
query ($login: String!, $first: Int, $after: String) {
user (login: $login){
avatarUrl
login
name,
followers(first: $first, after:$after) {
edges{
cursor
node{
id
name
login
avatarUrl
}
}
totalCount
},
repositories(first: $first) {
edges{
cursor
node{
id
name
}
}
totalCount
}
}
}
But I think it's bad to query huge data from server.
I have followers and repositories pages. So I think split this huge query to small queries is better.
Here is small queries:
followers query:
query($login: String!, $first: Int, $after: String) {
user(login: $login) {
followers(first: $first, after: $after) {
edges {
cursor
node {
id
name
login
avatarUrl
}
}
totalCount
}
}
}
repositories query:
query($login: String!, $first: Int, $after: String) {
user(login: $login) {
repositories(first: $first, after: $after) {
nodes {
id
name
}
totalCount
}
}
}
user query:
query($login: String!, $first: Int) {
user(login: $login) {
avatarUrl
login
name
}
}
Am I correctly? Is it necessary to do this? What's the best practice this situation? Is there any documentation for teaching people how to handle this or told people the best practice?

You can spit your queries into Fragments and in that way you would still only trigger one request and have smaller "queries". Something like this:
Fragment for followers:
fragment followers on User {
followers(first: $first, after: $after) {
edges{
cursor
node{
id
name
login
avatarUrl
}
}
totalCount
},
}
Fragment for repositories:
fragment repositories on User {
repositories(first: $first) {
edges{
cursor
node{
id
name
}
}
totalCount
}
}
Put them all together in the query:
query ($login: String!, $first: Int, $after: String) {
user (login: $login){
avatarUrl
login
name
...followers
...repositories
}
}

Related

GraphQL - search string in multiple fields

I am trying to search for a string across multiple fields with GraphQL.
I was able to use filter function with an or field, but it was not retrieving anything.
I want to be able to retrieve an array with all the items that contain the searched string in title or/and body ==> so if the query string was found in title or body retrieve it to array.
My code is:
const search_reviews= gql`
query SearchReviews ($my_query: String) {
reviews (filters: {title: {contains: $my_query}, or: {body: {contains: $my_query}} }) {
data{
id
attributes{
title
rating
body
categories{
data{
id
attributes
{
name
}
}
}
}
}
}
}
`
Works ok with only one field, but I want to have it in both fields
const search_reviews= gql`
query SearchReviews ($my_query: String!) {
reviews (filters: {body: {contains: $my_query} }) {
data{
id
attributes{
title
rating
body
categories{
data{
id
attributes
{
name
}
}
}
}
}
}
}
`
Seems that they changed the API.
Here is some code:
const search_reviews = gql`
query SearchReviews ($my_query: String!) {
reviews (filters: {or: [{body: {contains: $my_query} }, {title: {contains: $my_query}}]}) {
data{
id
attributes{
title
rating
body
categories{
data{
id
attributes
{
name
}
}
}
}
}
}
}
`
Basically you need to use $filters with an or to search in body or in the tile.
reviews (filters: {or: [{body: {contains: $my_query} }, {title: {contains: $my_query}}]})
Cheers to all!

GraphQL error: Variable $customerAccessToken of type String! was provided invalid value

I'm attempting to recover a customer using the customerAccessToken that is given when the user logs in to Shopify.
Using Apollo, here's my code:
this.apollo.mutate({
mutation: getCustomerFromToken,
variables: {
input: {
customerAccessToken: '217b9a6952c28eb4db376487a6301294' // Also tried btoa('217b9a6952c28eb4db376487a6301294')
}
},
})
Here's my GraphQL query:
query getCustomerFromToken($customerAccessToken: String!) {
customer(customerAccessToken: $customerAccessToken) {
id
addresses(first: 5) {
edges {
node {
address1
address2
company
city
province
zip
country
phone
}
}
}
orders(first: 200) {
edges {
cursor
node {
id
totalPriceV2 {
amount
currencyCode
}
processedAt
orderNumber
}
}
}
}
}
Here's the login GraphQL code I'm using to retrieve the accessToken from Shopify:
mutation customerAccessTokenCreate($input: CustomerAccessTokenCreateInput!) {
customerAccessTokenCreate(input: $input) {
customerAccessToken {
accessToken
expiresAt
}
customerUserErrors {
code
field
message
}
}
}
My problem was two fold.
I was using a mutation on a query end point
Queries don't use input in the payload
const payload = {
customerAccessToken: "..."
}
// NOT
const payload = {
input: {
customerAccessToken: "..."
}
}

Graphql with Apollo - refactor queries, return objects are repeating (same fields in diff queries)

I have several queries that have same return types:
// Query 1
gql`
mutation insert_shops_users($shopId: uuid) {
insert_shops_users(objects: [{ shopId: $shopId }]) {
affected_rows
returning {
Shop {
id
users {
userId
}
}
}
}
}
`,
// Query 2
gql`
mutation delete_shops_users_by_pk($shopId: uuid!, $userId: String!) {
delete_shops_users_by_pk(shopId: $shopId, userId: $userId) {
Shop {
id
users {
userId
}
}
}
}
`,
Now, I'd like to extract this part eg under name ShopUserResult and use that in both queries:
Extracted under ShopUserResult
Shop {
id
users {
userId
}
}
Resulting queries
// Query 1 - after refactor
gql`
mutation insert_shops_users($shopId: uuid) {
insert_shops_users(objects: [{ shopId: $shopId }]) {
affected_rows
returning {
ShopUserResult
}
}
}
`,
// Query 2 - after refactor
gql`
mutation delete_shops_users_by_pk($shopId: uuid!, $userId: String!) {
delete_shops_users_by_pk(shopId: $shopId, userId: $userId) {
ShopUserResult
}
}
`,
I'm quite new at graphql, any advice on refactoring would be much appreciated, thank you.
It's possible to refactor repeating sets of fields using fragments (source 1, source 2):
Query - before
gql`
mutation insert_shops_users($shopId: uuid) {
insert_shops_users(objects: [{ shopId: $shopId }]) {
affected_rows
returning {
Shop {
id
users {
userId
}
}
}
}
}
`,
Query - after using fragments
Fragment
const ShopWithUsers = gql`
fragment ShopWithUsers on shops {
id
users {
userId
}
}
`
Query
gql: gql`
mutation insert_shops_users($shopId: uuid) {
insert_shops_users(objects: [{ shopId: $shopId }]) {
affected_rows
returning {
Shop {
...ShopWithUsers
}
}
}
}
${ShopWithUsers}
`,

Github GraphQL API v4 Query on CommitAuthor

I am trying to run the following query on Githubs GraphQL api:
{
user(login: "davekaj") {
id
repositories(first: 10, orderBy: {field: NAME, direction: ASC}) {
nodes {
ref(qualifiedName: "master") {
target {
... on Commit {
history(first: 15, author: "WHAT DO I PUT HERE") {
totalCount
nodes {
additions
author {
name
user {
id
}
}
committedDate
deletions
}
}
}
}
}
}
}
}
}
It wants me to filter on a CommitAuthor for history(author: ). I tried passing my username, or my unique user ID, but it doesn't work. I am essentially passing it a string, but it wants the type CommitAuthor. How do I pass a CommitAuthor value?
It isn't clear to me, and I searched through the docs and the schema and I couldn't find anything.
Please help!
Ah, so the answer is actually very simple once I looked at the graphql documentation (rather than just the github documentation). CommitAuthor is an input type, which is described here https://graphql.org/graphql-js/mutations-and-input-types/.
The result is you pass an object of CommitAuthor. In this case I just have to pass the id, which looks like this: author: {id: "MDQ6VXNlcjIyNDE3Mzgy"}
See the completed code below.
{
user(login: "davekaj") {
id
repositories(first: 10, orderBy: {field: NAME, direction: ASC}) {
nodes {
ref(qualifiedName: "master") {
target {
... on Commit {
history(first: 15, author: {id: "MDQ6VXNlcjIyNDE3Mzgy"}) {
totalCount
nodes {
additions
author {
name
user {
id
}
}
committedDate
deletions
}
}
}
}
}
}
}
}
}

Get other related records (with id different that queried)

As a newbie to GraphQL I would appreciate some help in the following:
I have query which retrieves its author and that author's books. I would like the author's books to be author's other books, meaning - except the one being queried. What does it involve?
apollo-angular query:
const getBookQuery = gql`
query($id: ID){
book(id: $id){
id
name
year
author {
id
firstName
lastName
books { # <-- give me all _except_ the one with $id
name
year
id
}
}
}
}
`;
and in the schema.js (node.js server) I have something like:
const RootQuery = new GraphQLObjectType({
name: 'RootQueryType',
fields: {
book: {
type: BookType,
args: { id: { type: GraphQLID } },
resolve(parent, args) {
const { id } = args;
return Book.findById(id);
},
},
books: {
type: GraphQLList(BookType),
resolve() {
return Book.find({});
},
},
// ... other queries ...
}
})
The solution I am looking for should, obviously, not break other queries for books.
You should be able to achieve the exclusion by adding an argument to the Author type def and then appropriately using that argument in the resolver for books (which should be nested resolver on your Author type). Will need to adapt syntax for apollo-angular.
type Author {
id:
firstName: String
lastName: String
books(exclude: ID): [Book]
}
const resolverMap = {
Query: {
book(arent, args, ctx, info) {
...
}
},
Author: {
books(obj, args, ctx, info) {
// Use args.exclude passed to filter results
},
},
};
const getBookQuery = gql`
query($id: ID){
book(id: $id){
id
name
year
author {
id
firstName
lastName
books(exclude: $id) {
name
year
id
}
}
}
}
`;

Resources