如何为 GraphQL 服务器设计以下解析器? [英] How to design the following resolver for GraphQL server?

查看:27
本文介绍了如何为 GraphQL 服务器设计以下解析器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在用mysql和sequelize在meteor上使用react-apollo,我仍然是JS的初学者.让我们假设我的 apollo-server 上有以下解析器功能:

I am using react-apollo on meteor with mysql and sequelize, I am still a beginner in JS. Lets assume I have the following resolver function on my apollo-server:

 export default resolvers = {
     Query: {
         posts(_, args){
             return Post.findAndCountAll({ where: args   });
         },
         numberOfPosts(){
             return /// the number of selected posts
         }
     }

我想从数据库中选择一些满足某些条件的数据,然后计算所选行的数量并在numberOfPosts"字段中返回它们.findAndCountAll() 返回一个对象,其中包含选定的行和计数.我想让我的 post() 只返回选定的行,而我的 numberOfPosts() 只返回选定帖子的计数.现在,两者都由 posts() 返回.

I would like to select some data from the database where some conditions are met and then count the amount of selected rows and return them in the field "numberOfPosts". findAndCountAll() returns an object, which contains the selected rows and the count. I would like to get my post() to return only the selected rows, and my numberOfPosts() to return only the count of the selected posts. Right now, both is returned by posts().

我的架构是:

 type Post {
  id: Int
  date: Float
  text: String
}

 type NumberOfPosts{
  total: Int
  filtered: Int
}

type Query {
  posts(
   id: Ind,
   offset: Int,
   limit: Int,
   filter: String): [Post]
  numberOfPosts:[NumberOfPosts] 
}

schema {
  query: Query
}

目标是以下列格式接收数据:

{
  "data": {
    "numberOfPosts": [
      {
        "total": 1000,
        "filtered": 21
      }
    ],
    "posts": [
      {
        "id": 4,
        "date": 5105626122,
        "text": "jzybiwutudi"
      },
      ...
    ]
  }
}

我目前的工作:尝试 1:

  let selectedCount;
export default resolvers = {
    Query: {
        posts(_, args){
            return Post.findAndCountAll({where: args}).then(
                function (results) {
                    selectedCount = results.count;
                    return results.rows
                });
        },
        numberOfPosts(){
            return selectedCount
        }
    }}

所以我在解析器之外定义了一个帮助变量,并将其设置为所选行的数量,然后在 numberOfPosts() 中返回计数,这可行,但问题是, return results.rows 导致错误,我不明白为什么.

So I am defining a helping variable outside of resolvers, and set it to the number of selected rows, then the count is returned in numberOfPosts(), which works, but the problem with this is, return results.rows causes an error, and I do not understand why.

另一个问题是,selectedCount 总是前面的行数

another issue is, that selectedCount is always the previous number of rows

尝试 2

另一个似乎有效的解决方案是将参数两次传递到 GraphQL 查询中,如下所示:

Another solution that seems to work is to Pass the arguments twice into the GraphQL query, like so:

{
  numberOfPosts(filter: "example") {
    total
    filtered
  }
  posts(filter: "example") {
    id
    date
    text
  }
}

然后两个解析器函数都知道相同的参数,所以我可以选择和计算相同的帖子.但这对我来说看起来不对,因为我必须两次传递相同的参数,它们也会被传输两次......

Then both resolver functions know the same arguments, so I can select and count the same posts. But this looks not right to me, since I have to pass the same args twice, they will also be transmitted twice...

推荐答案

您应该更多地考虑设计以及每个查询应该做什么.这些查询不应改变数据库或全局状态.

You should think more about the design and what each of those queries should do. Those queries should not mutate the database or the global state.

你能做的最好的事情是简单地定义一个包含 totalfiltered 的新类型,就像你在 NumberOfPosts 中所做的那样您的第一次尝试,以及帖子列表.

The best thing you can do is to simply define a new type that includes total and filtered, like what you did as NumberOfPosts in your first try, and also the list of posts.

因此,您的架构将类似于:

So, your schema would be like:

type Post {
  id: Int
  date: Float
  text: String
}

type PostList {
  total: Int
  filtered: Int
  posts: [Post]
}

type Query {
  posts(
    id: Ind,
    offset: Int,
    limit: Int,
    filter: String): PostList
}

schema {
  query: Query
}

然后你解析 posts 像:

posts(_, args) {
  return Post.findAndCountAll({ where: args }).then(result => {
    return {
      total: 1000,
      filtered: result.count,
      posts: result.rows
    }
  })
}

请注意我是如何将 1000 作为总数.您无法使用 findAndCountAll 获取总行数.如果您需要,您可以并行运行两个不同的查询并使用 Promise.all 等待他们解决.

Notice how I just put 1000 for the total number. You can not get the total number of rows with findAndCountAll. If you that, need you can run two different queries in parallel and use Promise.all to wait for them to be resolved.

posts(_, args) {
  return Promise.all([
    Post.count(),
    Post.findAndCountAll({ where: args })
  ]).then(data => {
    return {
      total: data[0],
      filtered: data[1].count,
      posts: data[1].rows
    }
  })
}

上述代码也可以受益于 ES6 的解构:

The above code also could benefit from ES6's destructuring:

posts(_, args) {
  return Promise.all([
    Post.count(),
    Post.findAndCountAll({ where: args })
  ]).then(([totalCount, filteredData]) => {
    return {
      total: totalCount,
      filtered: filteredData.count,
      posts: filteredData.rows
    }
  })
}

现在您可以运行:

query {
  posts(filter:"example") {
    total
    filtered
    posts {
      id
      date
      text
    }
  }
}

并得到:

{
  "data": {
    "posts": {
      "total": 1000,
      "filtered": 21,
      "posts": [
        {
          "id": 4,
          "date": 5105626122,
          "text": "jzybiwutudi"
        },
        ...
      ]
    }
  }
}

这篇关于如何为 GraphQL 服务器设计以下解析器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆