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

Posted

技术标签:

【中文标题】Prisma:字段...未在...输入类型或类型中定义...预期但未提交对象【英文标题】:Prisma: Field ... is not defined in ... input type OR type ... expected but non object was submitted 【发布时间】: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。 当我尝试创建包含新卡或将其连接到现有卡的新脚本时,一切都按预期工作。 但是,如果我尝试创建脚本、卡片并在其中包含新任务,我会收到上面的错误消息。

    尝试以下突变时:
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 出现错误

    但是,这完全可以正常工作(没有任务的相同请求):
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 来检查它? 【参考方案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

【讨论】:

以上是关于Prisma:字段...未在...输入类型或类型中定义...预期但未提交对象的主要内容,如果未能解决你的问题,请参考以下文章

Type-GraphQL 上 JSON 字段的类型

PRISMA:如何在 prisma 常规类型中跳过 id 字段?

prisma introspect 生成无效模型

graphql prisma node js postgresql如何将创建日期/更新字段添加到graphql类型?

将 GraphQL/Prisma 字段设为私有/无法查询

Prisma GraphQL 模式和数据模型之间的同一字段可以有不同的类型吗?