Schema:
type Mutation {
removeProduct(id: String!): Product
}
type Product {
id: ID!
name: String!
slug: String!
description: String!
price: Float!
image: String!
ingredients: [String]
addOns: [String]
}
resolver:
exports.Mutation = {
removeProduct: async (parent, { id }, { Product }) => {
const deletedProduct = await Product.deleteOne({ id });
return deletedProduct;
},
};
query:
mutation{
removeProduct(id:"b55572b9-eb4d-46ea-a82f-f01cb0ba3993")
{
id
name
}
}
I need to remove a product from the db, but while deleting it, the response from graphql shows that "message": "Cannot return null for non-nullable field Product.name.",
It maybe because the product is deleted and nothing is returned because there is no product in db.
How do I write a query to delete a product ?
Note that it deletes the product from the db, but shows error in graphql response.
I'm running a query in GraphQL and getting this error:
{
"errors": [
{
"message": "Cannot read properties of null (reading '_doc')",
"locations": [
{
"line": 38,
"column": 5
}
],
"path": [
"songs",
0,
"creator"
]
}
],
"data": null
}
This is the query.
query {
songs {
song_file_name
song_type
song_size
user_name
creator {
email
}
This is my resolver file, and this is the schema.
const { buildSchema } = require('graphql');
module.exports = buildSchema(`
type Song {
_id: ID!
song_file_name: String!
song_type: String!
song_size: Int!
user_name: String!
creator: User!
}
type User {
_id: ID!
email: String!
password: String
createdSongs: [Song!]
}
input SongInput {
song_file_name: String!
song_type: String!
song_size: Int!
user_name: String!
}
input UserInput {
email: String!
password: String!
}
type RootQuery {
songs: [Song!]!
}
type RootMutation {
createSong(songInput: SongInput): Song
createUser(userInput: UserInput): User
}
schema {
query: RootQuery
mutation: RootMutation
}
`);
Could anyone help me figure out what I'm doing wrong? It looks like creator is returning null, but it is properly defined as far as I can tell. What's causing this?
Also, can anyone suggest a good place to learn GraphQL? I'm following this guide and though I find it useful and informative, it quickly gets to a level where I don't feel I fully understand what I'm doing although I'm following along.
I know the basics of GraphQL, but the relational concepts is hard for me to wrap my head around.
I'm trying to deploy my updated datamodel.prisma file. However, an error occurs and from what I can understand, it thinks that I'm trying to create a relation between an enum I defined above with the User type.
Here is my file:
enum Permission {
ADMIN
USER
ITEMCREATE
ITEMUPDATE
ITEMDELETE
PERMISSIONUPDATE
}
type User {
id: ID! #id
name: String!
email: String! #unique
password: String!
resetToken: String
resetTokenExpiry: String
permissions: [Permission]
}
type Item {
id: ID! #id
title: String!
description: String!
image: String
largeImage: String
price: Int!
createdAt: DateTime! #createdAt
updatedAt: DateTime! #updatedAt
}
Running prisma deploy --env-file variables.env gives me this error below:
Errors:
User
✖ Valid values for the strategy argument of `#scalarList` are: RELATION.
If I change permissions: [Permission] to permissions: Permission[], it gives this error instead (specifically, expected ImplementsInterfaces, DirectivesConst or FieldDefinitions):
ERROR: Syntax error while parsing GraphQL query. Invalid input "{\n id: ID! #id\n name: String!\n email: String! #unique\n password: String!\n resetToken: String\n resetTokenExpiry: String\n permissions: Permission[", expected ImplementsInterfaces, DirectivesConst or FieldDefinitions (line 10, column 11):
type User {
^
{
"data": {
"deploy": null
},
"errors": [
{
"locations": [
{
"line": 2,
"column": 9
}
],
"path": [
"deploy"
],
"code": 3017,
"message": "Syntax error while parsing GraphQL query. Invalid input \"{\\n id: ID! #id\\n name: String!\\n email: String! #unique\\n password: String!\\n resetToken: String\\n resetTokenExpiry: String\\n permissions: Permission[\", expected ImplementsInterfaces, DirectivesConst or FieldDefinitions (line 10, column 11):\ntype User {\n ^",
"requestId": "us1:ck6au2sum8frx0b00fviv1dom"
}
],
"status": 200
}
I'm not sure what that error means, but I do have a feeling that it doesn't understand the #unique type modifier at the email field. It wasn't there previously and deploys worked fine. Any help is greatly appreciated!
You need to specify the strategy and #scalarList directive.
This #scalarList(strategy: STRATEGY!) directive is required on any
scalar list field. The only valid argument for the strategy argument
is RELATION.
type Post {
tags: [String!]! #scalarList(strategy: RELATION)
}
It is required for all scalar and enum list fields.
See: https://www.prisma.io/docs/datamodel-and-migrations/datamodel-MYSQL-knul/##scalarlist
I have data model like below
type Tag {
id: ID!
name: String!
icon: String
description: String!
links: [Link!]!
}
type Link {
id: ID!
createdAt: DateTime!
description: String!
url: String!
tags: [Tag!]!
}
I want to query all the tags based on names and i am able to do that by the below query
tags (name:"tag1"){
id
name
}
this query works
but for the same query i want to return all the links associated with the tag name like below
tags(name:"tag1") {
id
name
links {
id
description
}
}
i am getting following error when executing this
"message": "Cannot return null for non-nullable field Tag.links.",
Resolver for this query
const tags = await context.prisma
.tags({name: args.name
})
graphql service 1 type defs:
import { gql } from 'apollo-server';
const typeDefs = gql`
type Post {
postId: ID!
postTitle: String!
postContent: String!
postAuthorId: ID
}
input PostTag {
name: String!
}
input PostInput {
postTitle: String!
postContent: String!
postAuthorId: ID!
postTags: [PostTag!]!
}
type CommonResponse {
code: Int!
message: String!
}
type Query {
posts: [Post]!
}
type Mutation {
addPost(post: PostInput): CommonResponse!
}
`;
export { typeDefs };
Now, graphql service 2 wants to extend PostTag input type from graphql service 1 like this:
import { gql } from 'apollo-server';
const typeDefs = gql`
extend input PostTag {
color: String
}
`;
export { typeDefs };
I print stitching schema, it's correct.
enum CacheControlScope {
PUBLIC
PRIVATE
}
type CommonResponse {
code: Int!
message: String!
}
type Mutation {
addPost(post: PostInput): CommonResponse!
}
type Post {
postId: ID!
postTitle: String!
postContent: String!
postAuthorId: ID
}
input PostInput {
postTitle: String!
postContent: String!
postAuthorId: ID!
postTags: [PostTag!]!
}
input PostTag {
name: String!
color: String
}
type Query {
posts: [Post]!
}
"""The `Upload` scalar type represents a file upload."""
scalar Upload
But when client sends a mutation like this:
mutation{
addPost(post: {
postTitle: "ez2on",
postContent: "golang",
postAuthorId: "1",
postTags: [{
name: "222",
color: "red"
}]
}){
code
message
}
}
Got this error:
{
"errors": [
{
"message": "Variable \"$_v0_post\" got invalid value { postTitle: \"ez2on\", postContent: \"golang\", postAuthorId: \"1\", postTags: [[Object]] }; Field \"color\" is not defined by type PostTag at value.postTags[0].",
"locations": [
{
"line": 7,
"column": 3
}
],
"path": [
"addPost"
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"errors": [
{
"message": "Variable \"$_v0_post\" got invalid value { postTitle: \"ez2on\", postContent: \"golang\", postAuthorId: \"1\", postTags: [[Object]] }; Field \"color\" is not defined by type PostTag at value.postTags[0].",
"locations": []
}
],
"stacktrace": [
"Error: Variable \"$_v0_post\" got invalid value { postTitle: \"ez2on\", postContent: \"golang\", postAuthorId: \"1\", postTags: [[Object]] }; Field \"color\" is not defined by type PostTag at value.postTags[0].",
" at new CombinedError (/Users/ldu020/workspace/github.com/mrdulin/apollo-graphql-tutorial/node_modules/graphql-tools/src/stitching/errors.ts:90:5)",
" at Object.checkResultAndHandleErrors (/Users/ldu020/workspace/github.com/mrdulin/apollo-graphql-tutorial/node_modules/graphql-tools/src/stitching/errors.ts:111:11)",
" at CheckResultAndHandleErrors.transformResult (/Users/ldu020/workspace/github.com/mrdulin/apollo-graphql-tutorial/node_modules/graphql-tools/src/transforms/CheckResultAndHandleErrors.ts:15:12)",
" at /Users/ldu020/workspace/github.com/mrdulin/apollo-graphql-tutorial/node_modules/graphql-tools/src/transforms/transforms.ts:37:45",
" at Array.reduce (<anonymous>)",
" at applyResultTransforms (/Users/ldu020/workspace/github.com/mrdulin/apollo-graphql-tutorial/node_modules/graphql-tools/src/transforms/transforms.ts:35:21)",
" at /Users/ldu020/workspace/github.com/mrdulin/apollo-graphql-tutorial/node_modules/graphql-tools/src/stitching/delegateToSchema.ts:104:12",
" at step (/Users/ldu020/workspace/github.com/mrdulin/apollo-graphql-tutorial/node_modules/graphql-tools/dist/stitching/delegateToSchema.js:31:23)",
" at Object.next (/Users/ldu020/workspace/github.com/mrdulin/apollo-graphql-tutorial/node_modules/graphql-tools/dist/stitching/delegateToSchema.js:12:53)",
" at fulfilled (/Users/ldu020/workspace/github.com/mrdulin/apollo-graphql-tutorial/node_modules/graphql-tools/dist/stitching/delegateToSchema.js:3:58)"
]
}
}
}
],
"data": null
}
It's important to keep in mind that makeRemoteExecutableSchema just "uses the [provided] link to delegate requests to the underlying service". When you query fields from the remote schema, it's delegating the request for those particular fields to the remote server, effectively rerouting the request. This is true whether you stitch the schema with some other one, or use it by itself.
Schema stitching allows you to combine any number of local and remote schemas. However, any remote schemas will still have their fields resolved by their respective servers.
Because stitching merges the provided schemas' type definitions, you can use the extend keyword inside one schema to modify types from another, even if it's a remote schema. If we extend an object type, we can also add some resolvers to help resolve the fields we've added.
Extending a remote schema's input object is a bit different. There's no "resolving" input objects. Instead, all we do by extending it is saying "these fields are also valid". However, when we request some remote schema field that takes this modified input object as an argument, the resolution of this field is, again, delegated to the underlying remote schema. It gets the modified input object and when it validates it, it finds extra fields and throws an error.
In other words, it's not possible to extend input types like this. And consider, even if the request didn't fail validation -- even if you extend the input type, the original resolver has not been changed and so it necessarily won't know how to handle the additional input type fields anyway.
NOTE: If you do the above but with two local schemas, the extension should work as expected because there is no delegation in this case. You're still left with a resolver that doesn't necessarily know how to handle the new input object field though.