Prisma:字段 ... 未在 ... 输入类型或类型中定义 ... 预期但未提交对象

Prisma: Field ... is not defined in ... input type OR type ... expected but non object was submitted

我正在使用 Prisma 1.34。来回 API 发展。通过本地主机游乐场对其进行测试。 提前为长文本道歉,无法理解我哪里出错了。

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

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 文件中定义的方案和我正在再次请求的方案,但不知道该往哪个方向走。

描述

先概括一个请求的全过程

The above image is taken from Prisma Basics in the official Prisma documentation.

如图所示,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取数据returns到API Server,完成第二次连接接受。 API Serverreturns数据到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