仅在graphql需要的情况下如何获取特定字段?
Posted
技术标签:
【中文标题】仅在graphql需要的情况下如何获取特定字段?【英文标题】:How to get specific field only in case if graphql require it? 【发布时间】:2020-03-27 16:04:12 【问题描述】:我已经开始学习 NestJs 和 GraphQL 并创建了一个简单的后端:
我有帖子:
import Field, Int, ObjectType from 'type-graphql';
@ObjectType()
export class Post
constructor ( id, title )
this.id = id;
this.title = title;
@Field(type => Int, nullable: true )
id: number;
@Field(type => String)
title: string;
我有用户
import Field, Int, ObjectType from 'type-graphql';
import Post from './post';
@ObjectType()
export class User
constructor( id, name, postIds )
this.id = id;
this.name = name;
this.postIds = postIds;
@Field(type => Int)
id: number;
@Field(type => String)
name: string;
@Field(type => [Int])
postIds: number[];
// in case 'postIds' populating
@Field(type => [Post])
posts: Post[];
而 NestJS(我认为 type-graphql
库做到了)为我生成 schema.gql 文件:
# -----------------------------------------------
# !!! THIS FILE WAS GENERATED BY TYPE-GRAPHQL !!!
# !!! DO NOT MODIFY THIS FILE BY YOURSELF !!!
# -----------------------------------------------
type Post
id: Int
title: String!
type Query
user(id: Int!): User!
type User
id: Int!
name: String!
postIds: [Int!]!
posts: [Post!]!
最后一个带有 UserResolver 的文件:
import Int, Resolver from 'type-graphql';
import Args, Query from '@nestjs/graphql';
import User from './models/user';
import Post from './models/post';
const post1 = new Post( id: 1, title: 'title_1' );
const post2 = new Post( id: 2, title: 'title_2' );
const post3 = new Post( id: 3, title: 'title_3' );
const user1 = new User( id: 1, name: 'Alex', postIds: [post1.id, post2.id] );
const user2 = new User( id: 2, name: 'Kate', postIds: [post3.id] );
const allUsers = [user1, user2];
const allPosts = [post1, post2, post3];
@Resolver()
export class UserResolver
@Query(returns => User)
user(@Args( name: 'id', type: () => Int ) id)
const currentUser = allUsers.find(u => u.id === id);
// please, remember next part of code
currentUser.posts = [];
currentUser.postIds.forEach(postId =>
const currentPost = allPosts.find(p => p.id === postId);
currentUser.posts.push(currentPost);
);
return currentUser;
就是这样。这很简单。现在,我可以请求下一个:
user(id:1)
name
posts
title
而且它有效。但是有一些问题。如果请求是下一个......
user(id:1)
name
postIds
#posts aren't required anymore
...下一个代码仍然执行
currentUser.posts = [];
currentUser.postIds.forEach(postId =>
const currentPost = allPosts.find(p => p.id === postId);
currentUser.posts.push(currentPost);
);
我认为这是不对的。 graphql 的想法是只获取查询中描述的必要数据。就我而言,我们得到posts
,然后将它们切断。如果将来会有大量的User.Post.IntroImage.Comment.User
嵌套,那么这将是无效的。
请告诉我怎么做对吗?
【问题讨论】:
【参考方案1】:我找到了答案:)
import Args, Parent, Query, ResolveProperty, Resolver from '@nestjs/graphql';
import User from './models/user';
import Post from './models/post';
const post1 = new Post( id: 1, title: 'title_1' );
const post2 = new Post( id: 2, title: 'title_2' );
const post3 = new Post( id: 3, title: 'title_3' );
const user1 = new User( id: 1, name: 'Alex', postIds: [post1.id, post2.id] );
const user2 = new User( id: 2, name: 'Kate', postIds: [post3.id] );
const allUsers = [user1, user2];
const allPosts = [post1, post2, post3];
@Resolver(of => User)
export class UserResolver
@Query(returns => User)
user(@Args('id') id: number)
return allUsers.find(u => u.id === id);
@ResolveProperty()
async posts(@Parent() user)
return user.postIds.map(postId =>
return allPosts.find(p => p.id === postId);
);
如果需要,我只需要添加 @ResolveProperty
和 graphql 库即可。
【讨论】:
以上是关于仅在graphql需要的情况下如何获取特定字段?的主要内容,如果未能解决你的问题,请参考以下文章
如何在不编写长查询的情况下查询所有 GraphQL 类型字段?
如何在不编写长查询的情况下查询所有 GraphQL 类型字段?
如何知道 Sangria GraphQL 中对象解析器中的请求字段
无法通过 Prisma 在 GraphQL-yoga 中使用片段