javascript - 如何为 GraphQL 服务器设计以下解析器?

标签 javascript graphql graphql-js apollo-server

我在 meteor 上使用 react-apollo 与 mysql 和 sequelize,我仍然是 JS 的初学者。 假设我的 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() 返回。

我的架构是:

 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 导致错误,我不明白为什么。

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

尝试 2

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

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

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

最佳答案

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

你能做的最好的事情就是简单地定义一个新类型,包括totalfiltered,就像你在NumberOfPosts中所做的一样你的第一次尝试,还有帖子列表。

因此,您的架构如下:

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(_, args) {
  return Post.findAndCountAll({ where: args }).then(result => {
    return {
      total: 1000,
      filtered: result.count,
      posts: result.rows
    }
  })
}

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

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'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"
        },
        ...
      ]
    }
  }
}

关于javascript - 如何为 GraphQL 服务器设计以下解析器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41434241/

相关文章:

graphql - Prisma Schema 中的多态性——最佳实践?

GraphQL : Using Relay without having to use edges & node

graphql - 升级到 graphql-js 15.0.0 会中断工作配置并显示消息 : Field "[...]" already exists in the schema

javascript - 如何在客户端sdk中提交带有payload.nonce的表单?我正在使用 Braintree 给出的示例?

javascript - CSS 根据另一个元素设置颜色

javascript - 覆盖 jQuery 自定义事件

react-native - 如何使用 AND/OR 运算符过滤列表/查询 AWS Amplify JavaScript GraphQL

javascript - 如何检测拉动刷新

relational-database - 解析相关对象的惯用且高效的方法是什么?

javascript - 如何在 Graphql 模式中定义日期数据类型?