【问题标题】:Prisma: Field ... is not defined in ... input type OR type ... expected but non object was submittedPrisma:字段...未在...输入类型或类型中定义...预期但未提交对象
【发布时间】:2019-11-30 11:47:40
【问题描述】:

我正在使用 Prisma 1.34。来自 API 开发。通过 localhost 游乐场对其进行测试。 抱歉,提前写了很长的文字,不明白我哪里出错了。

我有以下表示层次结构的方案脚本模板由卡片模板组成,卡片包括任务模板:

type ScriptTemplate {
  id: ID! 
  name: String!
  cards: [CardTemplate!]
  input: String!
  output: String!
}

type CardTemplate {
  id: ID!
  title: String!
  description: String
  tasks: [TaskTemplate!]
}

input ExistingCardTemplateInput {
  id: ID!
}

input NewCardTemplateInput {
  title: String!
  description: String!
  tasks: [NewTaskTemplateInput!]
}

type TaskTemplate {
  id: ID!
  label: String!
  description: String!
  cards: [CardTemplate!]
}

input ExistingTaskTemplateInput {
  id: ID!
}

input NewTaskTemplateInput {
  label: String!
  description: String!
}

对应的突变是:

type Mutation {
  createScriptTemplate(name: String!, input: String!, output: String!, cards: [ExistingCardTemplateInput!], new_cards: [NewCardTemplateInput!]): ScriptTemplate
  createCardTemplate(title: String!, description: String! tasks:[ExistingTaskTemplateInput!], new_tasks:[NewTaskTemplateInput!]): CardTemplate
  createTaskTemplate(label: String!, description: String! cards:[ExistingCardTemplateInput!]): TaskTemplate

}

所以基本上,如果我尝试使用 createTaskTemplate 突变或 createCardTemplate 突变 - 一切正常。我可以创建这些实体,包括使用其中的新任务创建新卡的嵌套突变或绑定现有任务。或现有卡到新创建的任务。这就是明确定义输入类型的原因:ExistingTaskTemplateInputNewTaskTemplateInputNewCardTemplateInput。 当我尝试创建包含新卡或将其连接到现有卡的新脚本时,一切都按预期工作。 但是,如果我尝试创建脚本、卡片并在其中包含新任务,我会收到上面的错误消息。

  1. 尝试以下突变时:
mutation{
  createScriptTemplate(
    name: "Script via API_H2"
    input: "Something describing initial state"
    output: "Something describing required state at the end"
    cards: [
      {
        id: "cjycl2nup00ta0703sd0kd8oa"
      },
      {
        id: "cjye3ryee01ey070383sxaoxz"
      }
    ]
    new_cards:[
      {
        title:"New card via scriptis2"
        description:"desc"
        tasks: [ 
          {
            description: "test dewscription"
            label: "test label"
          }
        ]
      },
      {
        title:"New card through scriptos2"
        description: "desc"
      }
    ]
  ){
    id
    name
    input
    output
    createdAt
    updatedAt
    cards{
      id
      title
      tasks{
        id
        label
      }
    }
  }
}

我有错误:

{
  "data": {
    "createScriptTemplate": null
  },
  "errors": [
    {
      "message": "Variable '$data' expected value of type 'ScriptTemplateCreateInput!' but got: 
{\"name\":\"First Script through API_H2\",\"input\":\"Something describing initial state\",\"output\":\"Something describing requred state at the end\",\"cards\":{\"connect\":[{\"id\":\"cjycl2nup00ta0703sd0kd8oa\"},{\"id\":\"cjye3ryee01ey070383sxaoxz\"}],\"create\":[{\"title\":\"New card via scriptis2\",\"description\":\"desc\",\"tasks\":[{\"label\":\"test label\",\"description\":\"test dewscription\"}]},{\"title\":\"New card through scriptos2\",\"description\":\"desc\"}]}}. 
Reason: 'cards.create[0].tasks' 
Expected 'TaskTemplateCreateManyWithoutCardsInput', found not an object. (line 1, column 11):\nmutation ($data: ScriptTemplateCreateInput!) {\n          ^",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "createScriptTemplate"
      ]
    }
  ]
}

实际请求如下所示(通过 console.log):

{ name: 'First Script through API_H2',
  input: 'Something describing initial state',
  output: 'Something describing requred state at the end',
  cards:
   { connect:
      [ [Object: null prototype] { id: 'cjycl2nup00ta0703sd0kd8oa' },
        [Object: null prototype] { id: 'cjye3ryee01ey070383sxaoxz' } ],
     create:
      [ [Object: null prototype] {
          title: 'New card via scriptis2',
          description: 'desc',
          tasks:
           [ [Object: null prototype] { label: 'test label', description: 'test dewscription' } ] },
        [Object: null prototype] { title: 'New card through scriptos2', description: 'desc' } ] } }

看起来我缺少 tasks 字段的 {connect or create} 位。 但是,当我将其更改为:

tasks: {create: [ 
          {
            description: "test dewscription"
            label: "test label"
          }
        ]
       }

Field \"create\" is not defined by type NewTaskTemplateInputField NewTaskTemplateInput.label and description of required type String! was not provided 出现错误

  1. 但是,这完全可以正常工作(没有任务的相同请求):
mutation{
  createScriptTemplate(
    name: "Script via API_H2"
    input: "Something describing initial state"
    output: "Something describing required state at the end"
    cards: [
      {
        id: "cjycl2nup00ta0703sd0kd8oa"
      },
      {
        id: "cjye3ryee01ey070383sxaoxz"
      }
    ]
    new_cards:[
      {
        title:"New card via scriptis2"
        description:"desc"
      },
      {
        title:"New card through scriptos2"
        description: "desc"
      }
    ]
  ){
    id
    name
    input
    output
    createdAt
    updatedAt
    cards{
      id
      title
      tasks{
        id
        label
      }
    }
  }
}

检查生成的方案,在那里找不到任何问题。

input TaskTemplateCreateManyWithoutCardsInput {
  create: [TaskTemplateCreateWithoutCardsInput!]
  connect: [TaskTemplateWhereUniqueInput!]
}

input TaskTemplateCreateWithoutCardsInput {
  id: ID
  label: String!
  description: String!
}

看起来我混淆了我在 gql 文件中定义的方案和我再次提出请求的方案,但不知道该往哪个方向发展。

【问题讨论】:

  • 我认为您必须在 tasks 中使用带有标签和描述的 create,或者在 connect 中仅使用 id。在这里,您使用 connect 带有标签和描述,没有 id。
  • @Errorname 对不起,我的错误示​​例。与“创建”相同的结果并不重要。我无法理解的是,因为我将tasks 的输入类型明确定义为[NewTaskTemplateInput!]。为什么 Prisma 有时会根据这种类型检查它,但同时会根据 TaskTemplateCreateWithoutCardsInput 来检查它?

标签: graphql graphql-js prisma prisma-graphql


【解决方案1】:

说明

首先概述一个请求的整个过程。

上图取自 Prisma 官方文档中的 Prisma Basics。

如图,localhost playground就是图中的clientlocalhost playground访问的Server就是图中的API Server,也就是Prisma Client。这里是第一个连接,图中绿色箭头。 Prisma Client 通过访问Prisma Server 从数据库中获取数据。这是第二个连接,图中黄色箭头。

数据流的过程,从localhost playground发送到API Server完成第一次连接传输,再经过resolve处理,使用Prisma Client发送到Prisma Server完成第二次连接传输。 Prisma Server根据请求的数据从Database中检索数据并返回给API Server,完成第二次连接接受。 API Server将数据返回给localhost playground,完成第一次连接的接受。一个完整的过程就完成了。

在使用Prisma的过程中,我们定义了两种schema,一种用于定义Prisma Server,名称通常为datamodel.prisma。另一种用于定义Prisma Client,如果定义在文件中,通常命名为schema.graphql,也可以通过模板字符串在JS文件中定义,还有其他方式,这里不深入讨论。您展示的内容属于Client Schema

成功完成这个过程需要每个部分发送的数据都是正确的。 您的第一个错误发生在发送第二个连接时。从API Server 发送的数据与Prisma Server 中的架构定义不匹配。 第二个错误是localhost playground发送的数据与发送第一个连接时API Server中的schema定义不匹配。

示例

假设以下架构

# datamodel.prisma
type User {
  id: @id!
  name: String!
  post: [Post!]!
}
type Post {
  id: @id!
  title: String!
}
# schema.graphql
input CreatePost {
  title: String!
}
type Mutation {
  createUser(name: String!,posts:[CreatePost])
}

使用以下变异创建用户

mutation {
  createUser(name: "prisma", posts: [{ title: "test" }]) {
    id
    name
  }
}

当从localhost playground发送到API Server时,数据如下

{
  "name": "prisma",
  "posts": [{ "title": "test" }]
}

如果将此数据直接发送给Prisma Server,则不符合Prisma Server的定义。您需要将数据转换为符合Prisma Server 架构的定义。

{
  "name": "prisma",
  "posts": { "create": [{ "title": "test" }] }
}

然后通过Prisma Client发送给Prisma Server

const resolve = {
  Mutation: {
    createUser: async (_, args) => {
      const userCreateInput = {
        name: args.name,
        posts: {
          create: args.posts,
        },
      }
      return await prisma.createUser(userCreateInput)
    },
  },
}

这样最终数据通过Prisma Server到达数据库。

解决问题

查看API ServercreateScriptTemplate的定义,应该是没有将接收到的数据转换成API Server要求的格式导致的错误。


Understand Prisma

【讨论】:

    猜你喜欢
    • 2017-12-24
    • 2017-08-16
    • 2019-08-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-09
    • 1970-01-01
    • 2016-06-29
    相关资源
    最近更新 更多