GraphQl如何将值分配给GraphQLObjectType

时间:2018-12-03 23:51:02

标签: node.js graphql

在我开始之前,代码可能看起来很冗长,但是仅围绕GraphQl的基础知识

我正在研究GraphQl并通过首先创建

进行了基础操作

书籍和作者的虚拟数据

let books = [
        { 
            name: "Got 1",
            genre: "Science Fictional",
            id: "1",
            authorId: "1"
        },
        {
            name: "Got 2",
            genre: "fictional",
            id: "2",
            authorId: "2"
        }
]

还有

let authors = [
    { 
        name: "Martin",
        age: 63,
        id: "1"
    },
    {
        name: "Martin 1",
        age:  48,
        id: "2"
    }

]

现在,我为这样的图书创建了一个objectType

const BookType = new GraphQLObjectType({  
    name: 'Book', 
    fields: () => ({
        id: { type: GraphQLID},
        name: { type: GraphQLString},
        genre: { type: GraphQLString },
        author: {
          type: authorType, 
          resolve (parents, args)  {
              for ( let i=0; i < authors.length; i++) {
                   if ( parents.authorId == authors[i].id) {
                       return authors[i]
                   }
            }
         }
    })
})

以及类似的作者

const authorType = new GraphQLObjectType({  
    name: 'author', 
    fields: () => ({
        id: { type:  GraphQLID},
        name: { type: GraphQLString},
        age: { type: GraphQLInt }
    })
})

现在,我之前的印象是,虚拟数据中的密钥应与对象类型中的密钥等效(例如,图书的虚拟数据中的 name ) >应该与我们在 BookType 字段中的 name 相同,对于Author来说也应如此),因此当我们从前端运行查询时,它看起来像

books(id: 2)
     name, 
     genre, 
     id 
     author: {
        name 
      }
   }

它相应地返回值。但是,我想我的印象不对,因为仔细查看 BookType 时,会有一个带有作者姓名的属性,但是在我们的书籍虚拟数据中,

(如果是这种情况,那么我们应该在BookType的属性中写入authorID)

[问题:] 那么,我的问题是GraphQl如何将数据分配给相应的查询?我不是故意写我的根查询,但是如果需要的话,让我知道,很乐意分享。

1 个答案:

答案 0 :(得分:1)

您的GraphQL终结点使用的架构不必匹配服务器使用的任何数据层提供的数据形状。您为特定GraphQLObjectType定义的字段仅定义客户端可以针对该类型查询哪些字段。

这意味着books数组中的每本书都可以具有一些其他属性(例如upcnumberOfCheckouts),但是该属性不一定必须在架构中公开。如果您有一个包含password字段和User类型的用户数据库表,则即使您包含其他字段,也可能不想将password公开为该类型的字段

同样,类型可以具有某些名称与基础数据不匹配的字段。在这里,每本书都没有author属性,但是Book类型却有。通过为该字段提供resolve函数,您可以告诉GraphQL如何解析该字段(或为其分配值)。

GraphQL如何解析字段值的确切逻辑可能不在此问题的范围内,但是您可以查看the spec以获得更多详细信息。这里相关的一点是,每个字段都必须解析为某个值。如果不提供resolve函数,则GraphQL使用默认解析器,该默认解析器在传递给解析器的 parent 对象中查找具有相同属性的属性。名称为要解析的字段。如果默认解析器找到具有相同名称的属性,则它将返回该属性的值;否则,它将返回该属性的值。否则,返回null。

这就是为什么您可以在不指定Book函数的情况下将字段添加到idnamegenre之类的resolve的原因-默认解析器正在做所有工作。

关于对象类型,重要的是要了解由返回对象类型的字段的解析器返回的值成为传递给该类型的字段field的解析器的父值

因此,如果字段的类型为[Book],则它的解析器将(如果正确实现)返回对象数组。例如,此数组可以是您问题中的伪数据。然后,该数组中的每个对象将传递给客户端查询中包含的resolve类型的 each 字段的Book函数。因此,如果客户仅对每本书要求idname,则将为父字段的解析程序返回的数组中的每本书运行这两个字段的resolve函数

resolve函数或解析器在父值,要解析的字段的参数以及整个请求的上下文中传递。所有信息均可用于解析您可能为特定类型任意定义的任何字段。

希望这可以为您提供更多的清晰度。构建模式时,您决定为类型定义哪些字段的决定可能由数据层决定,但不仅限于此。