首页 文章

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

提问于
浏览
5

我正在使用带有mysql和sequelize的meteor的react-apollo,我仍然是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()返回的 .

My schema is:

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
}

The Goal is to receive data in the following format:

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

My work so far: Try 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 始终是前一行数

Try 2

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

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

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

1 回答

  • 6

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

    您可以做的最好的事情就是简单地定义一个包含 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 像:

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

相关问题