Query elements where relationship is null - graphql

If I have a simple schema like:
type Author #model {
id: ID! #isUnique
posts: [Post!]! #relation(name: "AuthorOfPost")
}
type Post #model {
id: ID! #isUnique
author: Author #relation(name: "AuthorOfPost")
}
How can I query all Posts that do not have an author?
Unfortunately, I cannot find something in the authorFilter like id_is_null.

try this!
query PostsWithAuthor {
allPosts(filter: { author: null }) {
id
author {
id
}
}
}

Related

GraphQL extract possible queries from a schema

I have a graphql schema that i'm parsing
type User {
id: ID!
name: String!
email: String!
age: Int
posts: [Post!]!
}
type Post {
id: ID!
title: String!
body: String!
author: User!
comments: [Comment!]!
}
type Comment {
id: ID!
body: String!
author: User!
post: Post!
}
type Query {
users: [User!]!
user(id: ID!): User
posts: [Post!]!
post(id: ID!): Post
comments: [Comment!]!
comment(id: ID!): Comment
}
i want to get extract each possible query from it as a seperate string
in the above example,
String 1
type Query {
users: [User!]!
}
String 2
type Query {
user(id: ID!): User
}
String 3
type Query {
posts: [Post!]!
}
String 4
type Query {
post(id: ID!): Post
}
String 5
type Query {
comments: [Comment!]!
}
String 6
type Query {
comment(id: ID!): Comment
}
what is the best way to achieve this ? i'm using graphql javascript package

Prisma 2 delete mutation is returning null

I am using ApolloServer/Prisma2/GraphQL/Typescript/MySQL
I have created two models, User, and Post. My createUser and createPost mutations are working fine. However, I am having trouble getting my delete mutations working. Focusing on the deletePost, here is what I have in my code.
<<schema.graphql>>
type Query {
posts: [Post!]!
users: [User!]!
}
type Mutation {
createPost(title: String!, body: String!): Post!
createUser(name: String!, email: String!, password: String!): User!
deletePost(postId: ID!): Post
deleteAllPosts: [Post!]!
}
type Post {
id: ID!
title: String!
body: String!
author: User
published: Boolean!
}
type User {
id: ID!
name: String!
email: String!
posts: [Post!]!
}
<<schema.prisma>>
model Post {
id Int #id #default(autoincrement())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt #default(now())
title String
body String
published Boolean #default(false)
postedBy User? #relation(fields: [authorId], references: [id])
authorId Int?
}
model User {
id Int #id #default(autoincrement())
name String
email String #unique
password String
posts Post[]
}
<<Mutation.ts>>
async function deletePost(parent, { postId }, context, info) {
return await context.prisma.post.delete(
{
where {
id: parseInt(postId)
}
},
info
)
}
Note that the createPost and createUser are also in the Mutation.ts file and are working correctly. So I'm assuming there is no issue with the Apollo server.
When I use the GraphQL playground I use the following:
mutation {
deletePost(postId: "1") {
id
}
}
with the following result:
{
"data": {
"deletePost": null
}
}
I want the mutation to return the deleted post (at least the id if nothing else). In addition, the database is not deleting anything. I'd appreciate any help.

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)

authenticate user and serve only their related data

I have a schema in graphcool with these nodes (not sure what the correct term is here... leaf? node? model? type??)
type User #model {
auth0UserId: String #isUnique
createdAt: DateTime!
id: ID! #isUnique
userIdentifier: String
bundleIdentifier: String
updatedAt: DateTime!
devices: [Device!]! #relation(name: "UserOnDevice")
tokens: [Token!]! #relation(name: "TokenOnUser")
}
type Device #model {
id: ID! #isUnique
deviceIdentifier: String!
users: [User!]! #relation(name: "UserOnDevice")
token: Token #relation(name: "DeviceOnToken")
}
I'd like to make it so that a user must be authenticated and be related to the device data to be able to query on it. So, for a query like:
query($deviceIdentifier: String!) {
device(deviceIdentifier: $deviceIdentifier) {
id
}
}
This should return null unless they are autthenticated and are a user in the specified relation. I was thinking I needed a permission query like this one:
query ($node_id: ID!, $user_id: ID!) {
SomeDeviceExists(filter: {
id: $node_id,
users: {
id: $user_id
}
})
}
But it turns out that is invalid. How do I do it?
query ($node_id: ID!, $user_id: ID!) {
SomeDeviceExists(filter: {
id: $node_id,
users_some: {
id: $user_id
}
})
}
but this does require submitting the user_id in the request.

Entity Association syntax issue with graphql queries

I am trying to understand graphql's query and mutation syntax. Given this example:
type Author {
id: Int!
firstName: String
lastName: String
posts: [Post]
}
type Post {
id: Int!
title: String
author: Author
votes: Int
}
type Query {
posts: [Post]
author(id: Int!): Author
}
What should the queries look like to associate a post with the author? Is this where connections come into play or is that something else? Here is my attempt at trying to solve the problem but to avail.
mutation createAuthor {
createAuthor(input: {
id: 123
firstName: "Bob"
lastName: "Smith"
}) {
id
firstName
lastName
}
}
query listAuthors {
listAuthors {
items {
id
firstName
lastName
}
}
}
mutation createPost {
createPost(input: {
id: 12345
title: "Title"
votes: 345
author: {
lastName: {
contains: "Bob"
}
}
}) {
id
title
votes
author {
id
firstName
lastName
}
}
}
Any help on this would be appreciated. My Goal is to Query an author and return all of the post's associated with that author as well as create a Post Mutation that adds a post to an author.
There are 2 questions in one, so I'll answer in the order there were asked.
1. return all of the posts associated with an author
Your schema looks correct. The query would look like:
query {
author(id: 1) {
id
posts {
id
title
}
}
}
2. create Post and attach to an author
In your example if you want to expose an interface to create a Post, then you would have to expose a mutation field in your schema
e.g:
type Mutation {
createPost(input: CreatePostInput): Post
}
if you want at the same time of creating a post, to also attach it to an author then you could add the authorId as part of the input, here we only want to attach the Post to an existing Author:
input CreatePostInput {
title: String
authorId: ID!
votes: Int
}
of course this is only the interface definition. We need to actually create the Post and link it to the Author inside the resolver.
The mutation query will look like:
mutation createPost {
createPost(input: {
title: "Title"
votes: 345
authorId: "authorId1"
}) {
id
title
votes
author {
id
firstName
lastName
}
}
}
Hope that helps!

Resources