GqlGen – 在字段解析器中访问查询输入参数

huangapple go评论79阅读模式
英文:

GqlGen - Accessing query input params in field resolver

问题

使用GqlGen生成代码后,创建了一些字段解析器方法。我需要在字段解析器中访问查询输入参数,但我不确定如何访问它。
我需要从上下文中获取这些值吗?还是还有其他方法?

查询解析器:

func (r *queryResolver) Main(ctx context.Context, device string) (*models.Main, error) {
...
}

字段解析器:

// Version是version字段的解析器。
func (r *mainResolver) Version(ctx context.Context, obj *models.Main) (*models.Version, error) {
        // 我需要在这里访问传递给Main方法的device参数
	panic(fmt.Errorf("not implemented: Version - version"))
}

谢谢,

英文:

After generating the code using GqlGen there are some field resolvers method that has been created. I need to access the query input param in the field resolver but I'm not sure how to access it.
Do I need to get these values from context? Or is there any other way?

Query Resolver:

func (r *queryResolver) Main(ctx context.Context, device string) (*models.Main, error) {
...
}

Field Resolver:

// Version is the resolver for the version field.
func (r *mainResolver) Version(ctx context.Context, obj *models.Main) (*models.Version, error) {
        // I NEED TO ACCESS device param here which is passed in Main method
	panic(fmt.Errorf("not implemented: Version - version"))
}

Thanks,

答案1

得分: 2

我认为你可以在父解析器的FieldContext中找到参数。你可以使用graphql.GetFieldContext来获取它,就像这样:

// Version是version字段的解析器。
func (r *mainResolver) Version(ctx context.Context, obj *models.Main) (*models.Version, error) {
    device := graphql.GetFieldContext(ctx).Parent.Args["device"].(string)
    // ...
}

Args字段是一个map[string]interface{},所以你可以通过名称访问参数,然后将它们断言为它们应该是的类型。

如果解析器嵌套了多个级别,你可以编写一个函数,沿着上下文链向上查找,直到找到具有该值的祖先。使用Go 1.18+的泛型,该函数可以重用于任何值类型,使用类似于json.Unmarshal的模式:

func FindGqlArgument[T any](ctx context.Context, key string, dst *T) {
    if dst == nil {
        panic("nil destination value")
    }
    for fc := graphql.GetFieldContext(ctx); fc != nil; fc = fc.Parent {
        v, ok := fc.Args[key]
        if ok {
            *dst = v.(T)
        }
    }
    // 可选择在此处处理失败状态
}

并在代码中使用它:

func (r *deeplyNestedResolver) Version(ctx context.Context, obj *models.Main) (*models.Version, error) {
    var device string 
    FindGqlArgument(ctx, "device", &device)
}

如果这不起作用,还可以尝试使用graphql.GetOperationContext,这个函数基本上没有文档...(感谢@Shashank Sachan

graphql.GetOperationContext(ctx).Variables["device"].(string)
英文:

I think you can find the arguments in the FieldContext of the parent resolver. You can get it with graphql.GetFieldContext like this:

// Version is the resolver for the version field.
func (r *mainResolver) Version(ctx context.Context, obj *models.Main) (*models.Version, error) {
    device := graphql.GetFieldContext(ctx).Parent.Args["device"].(string)
    // ...
}

The field Args is a map[string]interface{}, so you access the arguments by name and then type-assert them to what they're supposed to be.

If the resolver is nested several levels, you can write a function that walks up the context chain until it finds the ancestor that has the value. With Go 1.18+ generics, the function can be reused for any value type, using a pattern similar to json.Unmarshal:

func FindGqlArgument[T any](ctx context.Context, key string, dst *T) {
	if dst == nil {
		panic("nil destination value")
	}
	for fc := graphql.GetFieldContext(ctx); fc != nil; fc = fc.Parent {
		v, ok := fc.Args[key]
		if ok {
			*dst = v.(T)
		}
	}
    // optionally handle failure state here
}

And use it as:

func (r *deeplyNestedResolver) Version(ctx context.Context, obj *models.Main) (*models.Version, error) {
    var device string 
    FindGqlArgument(ctx, "device", &device)
}

If that doesn't work, try also with graphql.GetOperationContext, which is basically undocumented... (credit to @Shashank Sachan)

graphql.GetOperationContext(ctx).Variables["device"].(string)

huangapple
  • 本文由 发表于 2022年9月29日 23:07:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/73897814.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定