Comments (7)
Hey @F21, I never tested it, but it could be done with the current graphql-js implementation? That would be such an interesting feature. A friend of mine ran into the same issue some weeks ago, we had to define the resolve in the parent even without needing all fields, for example:
{
memory {
virtual {
total
used
available
}
}
}
In memory
we have both virtual
and swap
, but we needed to resolve both virtual and swap data which leads to performance-related issues.
/cc @txgruppi
from graphql.
@CentaurWarchief I haven't really had a chance to play with the graphql-js
version (only went through the relay tutorial). However, I think the javascript implementation also has this limitation: graphql/graphql-js#154
The current work around is to resolve in the virtual
and swap
object and set the resolver of memory
to be empty:
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
return struct{}{}, nil
}
from graphql.
Our solution was to create a type for memory
and use it in the resolve function.
func NewMemoryData() *MemoryData {
return &MemoryData{}
}
type MemoryData struct {
Swap *SwapData `json:"swap"`
Virtual *VirtualData `json:"virtual"`
}
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
return NewMemoryData(), nil
},
from graphql.
This is kinda tricky, because the way the executor
works is by evaluating the query top-down.
As part of its pruning process, it would only look at the child if the parent node has something to evaluate.
I think it would be useful if a field that does not have a resolver is allowed to go "deeper", so that the child resolvers can resolve.
Every field actually has a default resolver, which you override by specifying it in the schema you defined.
So if the resolver (regardless if it's default or user-specified) returns a nil
value, the executor
won't try to see if its child fields has a value.
It is possible to design the executor
to try evaluate all child fields even when the parent field evaluates to nil
, but that could possibly lead to evaluating every field in the schema for every query.
In addition to that, having the value of resources
field to be nil but its own fields to have values are kinda counter-intuitive.
Consider:
type Car struct {
Name string
Year int
}
var car *Car
log.Println(car.Year) // <-- panic
@F21 solution of returning an empty anonymous struct at first glance seems hacky but is perfectly valid.
(It returns an empty but non-nil value), equivalent to:
var car Car
log.Println(car.Year) // 0
Can I suggest an alternate solution (which is practically the same as the one posted above), but probably more natural way of writing the schema.
type Memory struct {
Total float64 `json:"total"`
Used float64 `json:"used"`
}
type Resources struct {
Memory *Memory `json:"memory"`
}
func (resources *Resources) GetMemory() *Memory {
// resource-heavy operation to fetch stats
return &Memory {
Total: 1024,
Used: 100,
}
}
func main() {
resourceType := graphql.NewObject(graphql.ObjectConfig{
Name: "Resource",
Description: "Resource utilization information for a type.",
Fields: graphql.Fields{
"total": &graphql.Field{
Type: graphql.Float,
Description: "The total available.",
},
"used": &graphql.Field{
Type: graphql.Float,
Description: "The amount used.",
},
},
})
resourcesType := graphql.NewObject(graphql.ObjectConfig{
Name: "Resources",
Description: "Resource utilization information.",
Fields: graphql.Fields{
"memory": &graphql.Field{
Type: resourceType,
Description: "Memory utilization information.",
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
// `p.Source` is given by it's parent field `resources`
if resources, ok := p.Source.(*Resources); ok {
return resources.GetMemory(), nil
}
return nil, nil
},
},
},
})
queryType := graphql.NewObject(graphql.ObjectConfig{
Name: "Query",
Fields: graphql.Fields{
"resources": &graphql.Field{
Type: resourcesType,
Resolve: func(p graphql.ResolveParams) (interface{}, error) {
// pass `&Resource{}` down to it's child fields, available as `p.Source`
return &Resources{}, nil
},
},
},
})
...
}
from graphql.
@sogko Thanks for posting the sample code. That really helped!
I think your solution is exactly what I am looking for! 😄
from graphql.
@sogko Not sure if you meant to do something else but, this bit:
log.Printf(car.Year)
Panics because car.Year
is an int
while log.Printf
expects a string
. If you change to Println
or give it a format string it prints 0
as should be expected. Again, you may have meant something else but I just wanted to point that out.
from graphql.
@bbuck hahaha yeah thanks for pointing that out, it should be log.Println()
, I just meant to give an example of getting a value of a field from a nil struct, thanks! 👍🏻
from graphql.
Related Issues (20)
- New release?
- Potential goroutine leak in TestContextDeadline HOT 1
- Enums with trailing white space cause error.
- Playground
- make union input type ? it just have output union type
- With fiber HOT 1
- Printing GraphQL documents is slow HOT 1
- Bug with underscore and same name in keys from json response
- MongoDB _id field
- Printer returns invalid SDL if Block String comment contains double-quote
- When using custom scalar types, it's crucial to provide error feedback to users when issues arise with their submitted data. However, triggering exceptions within the ParseValue and ParseLiteral methods can lead to program crashes when using the graphql.Do method. This prevents the necessary error messages from being delivered to users.
- String type no longer recongised HOT 1
- Is it possible to go from `*graphql.Schema` to an ast node? HOT 1
- Error handling HOT 1
- Disabling Field Suggestions
- Is possible to typing typeConfig of graphql.Object after Object done.
- RootObjectFn request body always empty
- Unable to pass {{....}} as part of query or mutation string
- Redefining scalar ID
- How to support scalar JSON type? HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from graphql.