使用子字段从mongoose模式生成Graphql类型

使用子字段从mongoose模式生成Graphql类型,mongoose,graphql,graphql-js,Mongoose,Graphql,Graphql Js,我开始使用NodeJS和Mongoose构建一个Graphql服务,与已经在生产中的restapi一起使用,但是我在找到将Mongoose模式转换为Graphql类型的方法时遇到了一些困难 我有以下模式: var userSchema = new mongoose.Schema({ name: {type: String, required: true}, email: {type: String}, imageURL: {type: String, default:nu

我开始使用NodeJS和Mongoose构建一个Graphql服务,与已经在生产中的restapi一起使用,但是我在找到将Mongoose模式转换为Graphql类型的方法时遇到了一些困难

我有以下模式:

var userSchema = new mongoose.Schema({
    name: {type: String, required: true},
    email: {type: String},
    imageURL: {type: String, default:null},
    providerId: {type: String, required: true},
    token: {type: String, required: true},
    history: [{
        orders:[{type: mongoose.Types.ObjectId, ref:'Order'}],
        restaurant: {type: mongoose.Types.ObjectId, ref: 'Restaurant'}
    }]
}, { timestamps: true});
因此,基本上,问题在于
历史
字段。此字段是一个包含两个子字段的对象列表:orders(引用另一个mongoose模式的对象列表)和restaurant(引用restaurant的mongoose模式)


我的主要问题是:在为“User”编写相应的GraphQL类型时,是否有一种方法可以创建子字段,就像我在
history
字段中对mongoose所做的那样,或者我必须创建第二种类型,然后引用此类型(知道应用程序不需要在mongoose中创建另一个模式,而只需要在GraphQL中创建)。

正如您所说,当您编写GraphQL模式时,历史记录将需要是一个单独的类型,就像Order和Restaurant一样。使用Apollo,模式类型定义将类似于:

type User {
  # additional fields
  history: [Record!]!
}

type Record {
  orders: [Order!]!
  restaurant: Restaurant
}
除了上面的类型定义之外,您还将为用户提供一个解析器。在这种情况下,解析器只需返回
User.findOne()
(或者您通常从数据库获取用户对象的方式)

这里有一个巧妙的部分:您甚至可能不需要订单、餐厅甚至历史记录的解析程序。当您不指定解析程序时,GraphQL将使用默认的解析程序,该解析程序愉快地使用它所传递的对象(您将在用户类型的解析程序中传递的任何用户对象块)。如果它在该对象中找到与GraphQL架构的 类型定义,它将填充这些字段并忽略其他所有内容


当然,如果您需要额外的控制(可能您的对象键和字段名不匹配),您仍然可以自己编写解析器。

我的疑问是,我是否需要为历史创建一个单独的类型,因为我没有在Mongoose中创建。所以我会这样做。谢谢您的帮助explanation@ThiagoNascimento你可以用一个代替,但你严重限制了什么可以要求(即,任何请求该字段的人都无法将其进一步缩小到仅限于餐厅,或仅限于每个订单中的几个字段)。您还失去了在历史记录中轻松删除或模拟单个字段的能力。我不知道这一点,但我可能会选择单独的类型,以便在请求中具有更大的灵活性。还有一个问题:当使用mongoose ObjectID引用mongoose对象时,我是否必须在graphql解析器中填充该字段?因此可能会有一些问题类似于:User.find().populate(fields)是的,您可能需要为引用MongoDB中其他文档的任何字段调用populate。假设您让默认解析程序完成大部分繁重的工作,您将希望查询的解析程序返回与您在模式中概述的结构匹配的对象。