英文:
Golang gqlgen, fetching separate fields in a single DB query via Dataloading
问题
我正在尝试确定是否可能将具有自己的解析器的多个字段合并到单个数据库查询中,因为它们是从同一位置获取的。
例如,模式如下:
type ExampleResponse {
A: Int!
B: Int!
C: Int!
}
gqlgen.yml
配置文件如下:
models:
ExampleResponse:
fields:
A:
resolver: true
B:
resolver: true
C:
resolver: true
现在,如果在同一时间请求A和B,我希望从同一个数据库调用中获取它们。
我有一个基于键返回这些值的API:
exampleRes, err := resolver.service.GetExample(ctx, GetExampleRequest{
Keys: []ExampleKey{
AKey,
BKey,
},
})
这种方式是否可行,还是我需要重新考虑我的方法?
生成的解析器如下:
func (r *exampleResponseResolver) A(ctx context.Context, obj *model.ExampleResponse) (int, error) {
panic(fmt.Errorf("not implemented"))
}
func (r *exampleResponseResolver) B(ctx context.Context, obj *model.ExampleResponse) (int, error) {
panic(fmt.Errorf("not implemented"))
}
func (r *exampleResponseResolver) C(ctx context.Context, obj *model.ExampleResponse) (int, error) {
panic(fmt.Errorf("not implemented"))
}
英文:
I am trying to see if its possible to take several fields that have their own resolver and somehow get them in a single DB query since they are fetched from the same place.
Eg. the schema
type ExampleResposne {
A: Int!
B: Int!
C: Int!
}
The gqlgen.yml
models:
ExampleResponse:
fields:
A:
resolver: true
B:
resolver: true
C:
resolver: true
And now somehow I'd like to fetch A and B from a same DB call if they are requested at the same time
I have an API that returns these based on the keys
exampleRes, err := resolver.service.GetExample(ctx, GetExampleRequest{
Keys: []ExampleKey{
AKey,
BKey,
},
})
Is something like this possible or should I rethink my approach?
The generated resolvers
func (r *exampleResponseResolver) A(ctx context.Context, obj *model.ExampleResponse) (int, error) { panic(fmt.Errorf("not implemented"))
}
func (r *exampleResponseResolver) B(ctx context.Context, obj *model.ExampleResponse) (int, error) { panic(fmt.Errorf("not implemented"))
}
func (r *exampleResponseResolver) C(ctx context.Context, obj *model.ExampleResponse) (int, error) { panic(fmt.Errorf("not implemented"))
}
答案1
得分: 1
看起来你可能对一些主题有些混淆:
数据加载(Dataloading)
数据加载的概念是将多个数据请求批量处理在一个解析器的函数/方法调用下。这应该在解析类型的级别考虑,而不是在该类型的各个字段的级别考虑。
一个例子(来自https://gqlgen.com/reference/dataloaders/)是在一个数据库请求中解析多个Users
。
GraphQL字段解析器(Field Resolvers)
根据你的gqlgen.yml
配置,你已经为字段指定了单独的解析器,例如:
models:
ExampleResponse:
fields:
A:
resolver: true
...
字段解析器的概念是解析类型的各个字段,而不是将整个类型作为一个整体解析,实际上与数据加载的效果相反。这在我们尝试解析带有参数的字段或者代码拆分解析器逻辑时非常有用。
需要注意的是,如果使用不当,字段解析器经常会导致N+1问题。
解决方案
你可能没有看到类型ExampleResponse
的解析器,是因为你需要将查询入口点添加到Query
类型下。
schema.graphql
:
type Query {
getExample: ExampleResponse
}
然后运行:go run github.com/99designs/gqlgen generate
你应该会看到:
func (r *queryResolver) GetExample(ctx context.Context) (*model.ExampleResponse, error) {
panic(fmt.Errorf("not implemented"))
}
详细信息请参阅https://graphql.org/learn/schema/#the-query-and-mutation-types。
英文:
It seems you may have some topics confused:
Dataloading
The concept of dataloading is to batch multiple requests for data under one resolver's function / method call. This should be considered at the level of the resolving type and not at the level of individual fields of that type.
An example of this (taken from https://gqlgen.com/reference/dataloaders/) would be to resolve for multiple Users
under one database request.
Graphql Field Resolvers
With your gqlgen.yml
configuration, you have specified individual resolvers for fields with:
models:
ExampleResponse:
fields:
A:
resolver: true
...
The concept of field resolvers aim to resolve individual fields of a type rather than to resolve the type as a whole, essentially having the opposite effect to what dataloading has. This is useful when we are trying to resolve argumented fields or code splitting resolver logic.
To note, field resolvers can often cause N+1 problems when not used effectively.
The Solution
You might not be seeing a resolver for your type ExampleResponse
because you need to append your queries entry-point under the Query
type.
schema.graphql
:
type Query {
getExample: ExampleResposne
}
Then run: go run github.com/99designs/gqlgen generate
You should see:
func (r *queryResolver) GetExample(ctx context.Context) (*model.ExampleResponse, error) {
panic(fmt.Errorf("not implemented"))
}
See https://graphql.org/learn/schema/#the-query-and-mutation-types for details.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论