这些天我学会了使用GraphQL。我认为,要构建查询,我需要构建三个部分:
type User{
id String
name String
cars [Car!]!
}
type Car{
id String
}
type Query{
user(id: String): User
}
{
user: async function ({id}) {
const user = await DB.user.findOne({id});
const userCars = await DB.car.find({userId: id});
user.cars = userCars;
return cars;
}
}
{
user (id: "1") {
name
cars {
id
}
}
}
该查询返回用户名和他的汽车。数据库查询功能始终查询汽车。
但是有时候我只需要用户信息:
{
user (id: "1") {
name
}
}
我不想查询汽车,因此希望使我的数据库查询功能可以自动选择是否查询汽车。
我该怎么做?
答案 0 :(得分:1)
GraphQL.js将支持对象属性或解析器功能的方法;在Object Types的页面中对此进行了讨论。
一种解决方法是将匿名函数直接插入返回的对象中:
{
user: async function ({id}) {
const user = await DB.user.findOne({id});
user.cars = () => DB.car.find({userId: id});
return cars;
}
}
另一种方法是使用提供id
属性和(异步,惰性)cars
方法的类创建包装对象; GraphQL.js documentation中提供了一些示例。这种方法往往适用于大多数语言的大多数GraphQL实现。
答案 1 :(得分:0)
我认为您正在研究从GraphQL查询到数据库查询的自动创建/映射。
每个查询都是特定于数据库/项目的,因此您应该创建此映射。您可以使用graphql-fields软件包轻松地做到这一点。
包装中有复制粘贴的“为什么”部分:
基础REST api可能仅基于查询参数返回字段。
{ user { profile { firstName }, id } }
应请求
/api/user?fields=profile,id
同时
{ user { email } }
应请求
/api/user?fields=email
像这样实现您的解决方法:resolve(root, args, context, info) { const topLevelFields = Object.keys(graphqlFields(info)); return fetch(`/api/user?fields=${topLevelFields.join(',')}`); }
答案 2 :(得分:0)
最好避免将所有内容压缩到一个分解程序函数中。而是为Cars
创建一个单独的ObjectType,它具有自己的字段和自己的解析器功能。这样,仅在请求该字段时才调用汽车查询。
如果您使用的是RDS,请大声地加入数据和怪物,可以帮助优化查询的性能。