[英]How to design the following resolver for GraphQL server?
I am using react-apollo on meteor with mysql and sequelize, I am still a beginner in JS. 我正在使用带有mysql和sequelize的meteor的react-apollo,我仍然是JS的初学者。 Lets assume I have the following resolver function on my apollo-server:
假设我的apollo-server上有以下解析器函数:
export default resolvers = {
Query: {
posts(_, args){
return Post.findAndCountAll({ where: args });
},
numberOfPosts(){
return /// the number of selected 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". 我想从数据库中选择满足某些条件的一些数据,然后计算所选行的数量并在“numberOfPosts”字段中返回它们。
findAndCountAll()
returns an object, which contains the selected rows and the count. findAndCountAll()
返回一个对象,其中包含选定的行和计数。 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. 我想让我的
post()
只返回选定的行,而我的numberOfPosts()只返回所选帖子的数量。 Right now, both is returned by posts(). 现在,两者都是由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: 到目前为止我的工作:尝试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
}
}}
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. 所以我在解析器之外定义一个帮助变量,并将其设置为所选行的数量,然后在
numberOfPosts()
返回计数,这有效,但问题是, return results.rows
会导致错误,并且我不理解为什么。
another issue is, that selectedCount
is always the previous number of rows 另一个问题是,
selectedCount
始终是前一行数
Try 2 试试2
Another solution that seems to work is to Pass the arguments twice into the GraphQL query, like so: 另一个似乎有用的解决方案是将参数传递两次到GraphQL查询中,如下所示:
{
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...
但这看起来不对我,因为我必须两次传递相同的args,它们也会被传输两次......
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.
这些查询不应该改变数据库或全局状态。
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. 您可以做的最好的事情就是简单地定义一个包含
total
和filtered
的新类型,就像您在第一次尝试时作为NumberOfPosts
所做的那样,以及帖子列表。
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
}
And you resolve posts
like: 你解决了以下
posts
:
posts(_, args) {
return Post.findAndCountAll({ where: args }).then(result => {
return {
total: 1000,
filtered: result.count,
posts: result.rows
}
})
}
Notice how I just put 1000 for the total number. 请注意我如何将总数设为1000。 You can not get the total number of rows with
findAndCountAll
. 您无法使用
findAndCountAll
获取总行数。 If you that, need you can run two different queries in parallel and use Promise.all
to wait for them to be resolved. 如果你这样做,需要你可以并行运行两个不同的查询,并使用
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
}
})
}
The above code also could benefit from ES6's destructuring : 上述代码也可以从ES6的解构中受益:
posts(_, args) {
return Promise.all([
Post.count(),
Post.findAndCountAll({ where: args })
]).then(([totalCount, filteredData]) => {
return {
total: totalCount,
filtered: filteredData.count,
posts: filteredData.rows
}
})
}
Now you can run: 现在你可以运行:
query {
posts(filter:"example") {
total
filtered
posts {
id
date
text
}
}
}
and get: 得到:
{
"data": {
"posts": {
"total": 1000,
"filtered": 21,
"posts": [
{
"id": 4,
"date": 5105626122,
"text": "jzybiwutudi"
},
...
]
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.