仅在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 中使用片段

了解 GraphQL / Sangria-Graphql 中服务器端的特定字段

MySQL 唯一键仅在另一个键包含特定值的情况下