简体   繁体   English

在GraphQL中,如何实现可选查询?

[英]In GraphQL, how do I implement optional queries?

EDIT: Since it doesn't seem to be clear, I am specifically asking about the DB requests I should be making inside the resolve function for a query on the backend. 编辑:由于目前尚不清楚,我特别在问有关数据库请求的信息,我应该在用于查询后端的resolve函数中提出该数据库请求。

I am implementing GraphQL queries, and I am having trouble understanding exactly how many calls I should make in a given query. 我正在实现GraphQL查询,并且在确切了解我应该在给定查询中进行多少次调用时遇到了麻烦。 For example, here's a data structure with users and clubs that the user can join: 例如,这是一个包含用户和俱乐部的数据结构,用户可以加入该俱乐部:

User {
  UserID
  Clubs
  OtherStuff
}

Club{
  ClubID
  ClubName
}

I have the following calls I can make to my DB: 我可以对数据库进行以下调用:

  • Get all UserIDs 获取所有用户ID
  • Get info for UserID 获取有关UserID的信息
  • Get all ClubIDs for a user 获取用户的所有ClubID
  • Get info for ClubID 获取有关ClubID的信息

The thing I don't understand is whether I should be making all of these calls every time Users is queried. 我不明白的是,是否应该在每次查询用户时都拨打所有这些电话。 If someone is only querying UserIDs, it seems like a huge waste to retrieve everything else. 如果某人仅查询UserID,则检索其他所有内容似乎是巨大的浪费。 Should Clubs for User be a totally separate GraphQL query, should Clubs only return ClubIDs, or is there a way to efficiently allow full Club info to be available in the Clubs field? Clubs for User应该是一个完全独立的GraphQL查询吗,Clubs应该只返回ClubID,还是可以有效地在Clubs字段中提供完整的Club信息?

EDIT 2: Ok so here's my code. 编辑2:好的,这是我的代码。 I've commented the part where I'm not sure what to do. 我已经评论了我不确定该怎么做的部分。

const QueryType = new GraphQLObjectType({
  name: 'Query',
  fields: {
    User: userQueryField,
    Club: clubQueryField
  }
});

const clubQueryField = {
  type: new GraphQLList(ClubType),
  args: {
    UserID: {
      description: 'Returns all clubs the user is a part of',
      type: GraphQLID
    }
  },
  resolve(root, {UserID}) {
    //.....
  }
};


const userQueryField = {
  type: new GraphQLList(UserType),
  args: {
    UserID: {
      description: 'If omitted, returns a list of all users. \
      Otherwise, returns the user with the provided ID',
      type: GraphQLID
    }
  },
  resolve(root, {UserID}) {
    if(UserID){
      return new Promise((resolve, reject) => {
        getUserInfo(UserID, function(response){

          //HERE: I have tried different things, like clubQueryField(UserID) and clubQueryField.resolve, but with no luck
          UserID.Clubs = clubQueryField
          resolve([response]);
        });
      });
    }
  }
};

EDIT 3: UserType definition. 编辑3:UserType定义。

const UserType = new GraphQLObjectType({
  name: 'User',
  fields: () => ({
    UserID: {
      type: GraphQLID
    },
    Clubs: {
      type: new GraphQLList(ClubType)
    }
  })
});

GraphQL has a lazy loading feature that takes care of other fields in the query. GraphQL具有延迟加载功能,可处理查询中的其他字段。 If user writes the following query: 如果用户编写以下查询:

query{
   users{
    id
   }
}

it gets the user ids and it does not looking for other fields obviously. 它获取用户ID,并且显然不会寻找其他字段。 It definitely depends on your resolver though. 当然,这绝对取决于您的解析器。 If you write the resolver something like this: users { resolve: body => get_user_id} , it gets the user ids from the database. 如果您编写的解析器是这样的: users { resolve: body => get_user_id} ,它将从数据库中获取用户ID。 Hope this helps! 希望这可以帮助!

GraphQL APIs are organized in terms of types and fields, I recommend creating separate queries for User types and Club types, if someone is querying only userIds they will use the user query. GraphQL API按照类型和字段进行组织,我建议为用户类型和俱乐部类型创建单独的查询,如果有人仅查询userId,则他们将使用用户查询。

query for user: 查询用户:

query {
  users {
   id
  }
}

query for club: 查询俱乐部:

query {
  club {
   clubID
   clubName
   userId
  }
}

if someone is trying to querying users/club you can add the club type to the User type like this: 如果有人试图查询用户/俱乐部,则可以将俱乐部类型添加到用户类型中,如下所示:

query {
  users {
   id
   club {
    clubID
    clubName
   }
  }
}

in your user type there will be a field called club which is going to be type club and in the resolver it will call the club query with obj.userId as a parameter, the beauty of GraphQL is that you let the client decide what fields to fetch. 在您的用户类型中,将有一个名为club的字段,它将是club类型,而在解析器中,它将使用obj.userId作为参数来调用club查询, obj.userId的优点在于,您可以让客户端决定要取。

you can see an example of nested query here 您可以在此处看到嵌套查询的示例

EDIT: Then in your case you can modify your userType to include clubs where the user belongs to, you don't need that condition in your clubQueryField the condition will be on the query the client is making, so let say your user type is this: 编辑:然后在您的情况下,您可以修改userType以包括该用户所属的俱乐部,您不需要在clubQueryField该条件,该条件将取决于客户clubQueryField在执行的查询,所以可以说您的用户类型是:

UserType: 用户类型:

export default new GraphQLObjectType({
  name: 'UserType',
  fields: {
    userId: {
      description: 'user id',
      type: GraphQLString
    },
    email: {
      description: 'user email',
      type: GraphQLString
    },
    clubs: {
      description: 'User clubs',
      type: new GraphQLList(ClubType),
      resolve: (obj, args, _) => {
        return getUserClubs(obj.userId);
      }
    },
  }
});

then if your client needs only the user it will request something like this: 然后,如果您的客户仅需要用户,它将请求以下内容:

  query {
    User {
     userId
     email
     }
  }

and if the client needs user and clubs it will request something like this: 如果客户需要用户和俱乐部,它将请求以下内容:

query {
    User {
     userId
     email
     clubs {
        field1
        field2
       }
     }
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM