从带有子字段的猫鼬模式生成 Graphql 类型
Posted
技术标签:
【中文标题】从带有子字段的猫鼬模式生成 Graphql 类型【英文标题】:Generate Graphql Type from mongoose schema with subfields 【发布时间】:2017-12-13 00:28:44 【问题描述】:我开始使用 NodeJS 和 Mongoose 构建一个 Graphql 服务以与已经投入生产的 REST api 一起使用,但是我在寻找将我的 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);
所以,基本上,问题在于history
字段。该字段是一个包含 2 个子字段的对象列表:orders(引用另一个 mongoose 架构的对象列表)和 restaurant(引用餐厅的 mongoose 架构)。
我的主要问题是:在为“用户”编写相应的 GraphQL 类型时,有没有办法创建子字段,就像我在 history
字段上使用猫鼬所做的那样,或者我必须创建第二个类型然后引用这种类型(知道应用程序不需要在 mongoose 中创建另一个模式,而只能在 GraphQL 中创建)。
【问题讨论】:
【参考方案1】:正如您所说,当您编写 GraphQL 架构时,历史记录需要是一个单独的类型,订单和餐厅可能也是如此。使用 Apollo,模式类型定义如下所示:
type User
# additional fields
history: [Record!]!
type Record
orders: [Order!]!
restaurant: Restaurant
除了上述类型定义之外,您还可以为 User 提供解析器。在这种情况下,解析器将简单地返回 User.findOne()
(或者您通常从数据库中获取 User 对象)。
这是一个简洁的部分:您甚至可能不需要用于 Order、Restaurant 甚至 History 的解析器。当您不指定解析器时,GraphQL 将使用默认解析器,该解析器会愉快地使用它传递的对象(无论您将在解析器中为 User 类型传递的 User 对象的任何块)。如果它在该对象中找到与您在 GraphQL 模式中指定的字段匹配的键 类型定义,它将填充这些字段并忽略其他所有内容。
当然,如果您需要额外的控制(可能您的对象键和字段名称不匹配),您仍然可以自己编写解析器。
【讨论】:
我真的怀疑是否需要为历史创建一个单独的类型,因为我没有在 Mongoose 中。所以我会这样做。谢谢解释 @ThiagoNascimento 您可以改用JSON custom scalar,但随后您将严格限制可以请求的内容(即,任何请求该字段的人都无法将其进一步缩小到仅餐馆,或每个订单中的几个字段)。您也无法轻松地删除或模拟历史记录中的各个字段。 不知道,但我可能会选择不同的类型,这样我可以在请求中拥有更大的灵活性 还有一个问题:使用 mongoose ObjectID 引用 mongoose 对象时,是否必须在 graphql 解析器中填充该字段?所以它会是这样的: User.find().populate(fields) 是的,大概您需要为引用 MongoDB 中其他文档的任何字段调用填充。假设您让默认解析器完成大部分繁重的工作,您将希望查询的解析器返回一个与您在架构中概述的结构相匹配的对象。以上是关于从带有子字段的猫鼬模式生成 Graphql 类型的主要内容,如果未能解决你的问题,请参考以下文章