Apollo GraphiQL browser playground: How to nest queries? - graphql

Wish to run a nested query within as Apollo GraphiQL browser playground.
Schema for two queries intended to be nested and a response type:
getByMaxResults(maxResults: Int = null): [ID!]!
appById(id: ID!): AppOutputGraphType
AppOutputGraphType = {
accountIdGuid: ID!
createdAt: DateTime!
description: String!
id: ID!
updatedAt: DateTime!
userId: ID
}
Query getByMaxResults: [ID!]!, the result is an array of element ID:
Query appById(id: ID!) requesting a couple of AppOutputGraphType fields:
Is there a way within the GraphiQL browser sandbox to nest these two Queries?:
query getByMaxResults gather an array of IDs.
Iterate this array and perform multiple queries appById with each ID.
Thank you

Change your definition of the getByMaxResults query to:
getByMaxResults: [AppOutputGraphType!]!
Change your resolver to return an array containing all the fields of the AppOutputGraphType objects and not just the id.
Then just:
query {
getByMaxResults {
id
updatedAt
}
}
There is no way in GraphQL to nest queries but the whole point of the language is to remove the need to do so.
With the proper resolvers you could even get the related account and user for each AppOutputGraphType.
Change:
AppOutputGraphType = {
account: Account <= don't include foreign keys, refer to the related type
createdAt: DateTime!
description: String!
id: ID!
updatedAt: DateTime!
user: User <= don't include foreign keys, refer to the related type
}
Then you can do queries like:
query {
getByMaxResults {
id
updatedAt
account {{
id
name
city
}
user {
id
firstName
lastName
}
}
}

Related

How to properly append to an array using Dgraph GraphQL API?

I'm trying to spin up Dgraph, but appears as though to add a node to an array of nodes using the GraphQL api requires an unnecessary amount of work if I understand it correctly:
I have the following simplified schema:
type User #secret(field: "password") {
account: String! #id
email: String! #search(by: [hash])
extension: String! #search(by: [hash])
phone: String! #search(by: [hash])
hasCreated: [Transaction]! #hasInverse(field: from)
hasReceived: [Transaction]! #hasInverse(field: to)
}
type Transaction {
id: ID!
type: TransactionType! #search(by:[terms])
amount: Float!
assetCode: String! #search(by:[terms])
to: User!
from: User!
initiatedAt: DateTime! #search(by:[hash])
completedAt: DateTime #search(by:[hash])
status: Status!
}
To me, it appears as though to add a node to the User's hasCreated or hasReceived fields would require me to pull the entire array, append a new Transaction to the array and then use an updateUser mutation to complete the update. But the updateUser mutation would require me to get all the Transactions and all Users attached to these transactions and so on.
Example trying to retrieve an entire user object:
query {
getUser(id:"%s"){
account
email
extension
phone
hasCreated {
id
type
amount
assetCode
to {
...
}
}
hasReceived {
id
type
amount
assetCode
to {
...
}
}
}
}
}
Is there another way to append to arrays or update objects using the GraphQL api without having to retrieve whole objects?

why I cannot fetch related fields on my prisma query with my GO client?

I am very very new in Prisma but so far I managed to do queries and map it using graphql, but then I noticed that I was not fetching the whole information.
Here is what I have.
I have a table called Highlight
The table has a relation to HighlightItems (that is a wrapper to fetch a postId, number of votes , etc, etc)
so I mapped my prisma objects and seem to be working...
I have this in my datamodel.prisma
type Highlight {
id: UUID! #id
highlightId: String! #unique
createdAt: DateTime! #createdAt
updatedAt: DateTime! #updatedAt
highlightItems: [HighlightItem!]!
#relation(
link: TABLE
name: "HighlightItemByHighlight"
onDelete: CASCADE
)
and at my HighlightItem
type HighlightItem {
id: UUID! #id
createdAt: DateTime! #createdAt
updatedAt: DateTime! #updatedAt
lastComment: String ....
I was able to generate the prisma model and use the generated mutations:
mutation {
createHighlight(....
and I am able to query directly the prismadb with the queries:
query {
highlights{
highlightId, highlightItems{id}
}
}
Now I have the issue when working with my GO resolver
when I do this:
func (r *queryResolver) Highlights(ctx context.Context, first, last *int, before, after, search *string, input string, input2 string ) (*models.Highlights, error) {
allHighligts, err := prisma.Instance.Highlights(
&prisma.HighlightsParams{
}).Exec(ctx)
....
Then I realize that I cannot get the HighlightItems through Highlight, checked the document on the prisma client for GO and it should use the "fluent API"
https://www.prisma.io/docs/prisma-client/basic-data-access/reading-data-GO-go05/#relations
but so far I am not able to fetch them, any idea what Im doing wrong?
This problem can be about capitalize variable names. Can you do uppercase first letter of variables?

How to resolve subselections / relations in prisma (nested lists)

Let's take an example from the github repo of prisma:
We have a user, the user could have multiple posts, and one post could have multiple links.
My goal is, to retrieve all posts and all links.
This means, my response is a list (links) in a list (posts).
I want to map the values I get back as two nested lists.
datamodel.prisma
type User {
id: ID! #id
email: String! #unique
name: String
posts: [Post]!
}
type Post {
id: ID! #id
createdAt: DateTime! #createdAt
updatedAt: DateTime! #updatedAt
published: Boolean! #default(value: false)
title: String!
content: String
author: User!
links: [Link]!
}
type Link {
id: ID! #id
url: String
title: String
post: Post!
}
schema.graphql
type Query {
...
}
type Mutation {
...
}
type Link {
id: ID!
url: String
title: String
post: Post!
}
type Post {
id: ID!
createdAt: DateTime!
updatedAt: DateTime!
published: Boolean!
title: String!
content: String
author: User!
}
type User {
id: ID!
email: String!
name: String
posts: [Post]!
}
I want to query all posts of a user, and all of the links for every post in the response.
How would I query this request?
user {
id
posts {
id
links {
id
}
}
}
The above code snipper would not work.
EDIT
I want to use the following:
User: {
listPosts: (parent, args, context, info) {
return context.prisma.posts().links()
}
}
So in my response (data in front-end via react-apollo Query Component), I want to map over posts AND the links in each post.
BUT the links attribute in posts is null.
Is there another way to achieve this?!
According to the docs:
Prisma client has a fluent API to query relations in your database. Meaning you can simply chain your method calls to navigate the relation properties of the returned records. This is only possible when retrieving single records, not for lists. Meaning you can not query relation fields of records that are returned in a list.
In order to get around that limitation, you can use the $fragment method:
const fragment = `
fragment UserWithPostsAndLinks on User {
id
email
name
posts {
id
title
content
links {
id
url
title
}
}
}
`
const userWithPostsAndLinks = await prisma.user({ id: args.id }).$fragment(fragment)

Prisma data modeling has many and belongs to

I have a prisma data model that consists of a root Category and a Subcategory. A Category has many Subcategories and a Subcategory belongs to one Category. My model looks like this:
type Category {
id: ID! #unique
createdAt: DateTime!
updatedAt: DateTime!
name: String!
subCategories: [SubCategory!]! #relation(name: "Subcategories")
}
type SubCategory {
id: ID! #unique
createdAt: DateTime!
updatedAt: DateTime!
name: String!
category: Category! #relation(name: "ParentCategory")
cards: [Card!]! #relation(name: "SubCategoryCards") #Category #relation(name: "CardCategory")
}
Now when i go to create a new subcategory and via
mutation {
createSubCategory(data:{
name:"This is a test"
category:{
connect:{
id:"cjp4tyy8z01a6093756xxb04i"
}
}
}){
id
category{
name
id
}
}
}
This appears to work fine. Below I query for the subcategories and their parent Category and I get the results that I expect.
{
subCategories{
id
name
category{
id
name
}
}
}
However, when i try to query a category, and get all of it's sub categories I'm getting an empty array:
{
categories{
id
name
subCategories{
id
name
}
}
}
How can I query all categories and get their sub categories?
As per the documentation, the #relation directive is used to specify both ends of a relation.
Let's take the following datamodel:
type User {
postsWritten: [Post!]!
postsLiked: [Post!]!
}
type Post {
author: User!
likes: [User!]!
}
Here, we have an ambiguous relation between Post and User. Prisma needs to know which User field (postsWritten? postsLiked?) to link to which Post field (author? likes?)
To resolve this, we use the #relation with a name used in both ends of the relation.
This would make the datamodel look like this:
type User {
postsWritten: [Post!]! #relation(name: "AuthorPosts")
postsLiked: [Post!]! #relation(name: "UserLikes")
}
type Post {
author: User! #relation(name: "AuthorPosts")
likes: [User!]! #relation(name: "UserLikes")
}
Because we used the same name for the postsWritten and author fields, Prisma is now able to link these two in the database. Same for postsLiked and likes.
In conclusion, the problem with your datamodel is that you used different names in your relation. This confuses Prisma which think those are different relations. Which explains why you can query one way but not another.

How to "upsert" an array/nested field when issuing update mutation in Graphcool / GraphQL?

I have a Post type than has a tag field which can be associated with many Tag entries (man-to-many relationship). The issue I am running into is when updating a Post - I need to both create and associate new Tag's for tags that do not yet exist, while preserving the existing Post->Tag relationships. Basically, what I am looking for is something akin to an upsert when issuing a mutation update on a nested one-to-many field.
Here is my schema:
type Post #model {
createdAt: DateTime!
createdBy: User #relation(name: "PostsByUser")
description: String #defaultValue(value: "''")
id: ID! #isUnique
tags: [Tag!]! #relation(name: "TagsOfPost")
...
}
type Tag #model {
id: ID! #isUnique
tag: String!
createdBy: User #relation(name: "TagsByUser")
createdAt: DateTime!
posts: [Post!]! #relation(name: "TagsOfPost")
}
This mutation works to update a Post and add new tags, but overwrite all of the existing values in the Post's tag field:
mutation updatePost(
$id: ID!
$createdById: ID!
$timestamp: DateTime!
$description: String
$tags: [PosttagsTag!]!
) {
updatePost(
id: $id
createdById: $createdById
timestamp: $timestamp
description: $description
tags: $tags
) {
id
timestamp
description
tags {
id
tag
}
createdBy {
id
username
}
}
}
I came across this post by #marktani but it's not clear how to implement the combined method he outlines:
Combined
You can also use tags and tagsIds in the same mutation, this would connect the new Tutorial node to all the tags in tagsIds and connect it to the new tags in tags. This is what you want to do if you want to only allow tags with a unique text, so for a new Tutorial, there will likely be some tags that already exists, and some that need to be created.
Is it currently impossible to do this with one mutation? Would a second mutation be required after updating the post with new tags to re-establish the associations between the Post and existing Tag ids, i.e., having to repeatedly call addToTagsOfPost(tagsTagId: ID!
postsPostId: ID!)? Thanks!
Ok, so there is currently a Graphcool bug where passing in both tags and tagsIds to the mutation will create and associate newly created Tags but will not add the tagsIds associations to existing Tags. I posted an issue on Graphcool's GitHub repo and they have acknowledged it - https://github.com/graphcool/framework/issues/1288

Resources