GraphQL query with nested query passing parameters to non scalar type arguments - graphql

I have a current Query type defined like this:
type BoxItems {
total: Number,
boxItems: [BoxItem]
}
type Box {
boxItemUuid: UUID!
boxItems:(page: Number, pageSize: Number): BoxItems
}
extend Query {
boxes(input: SomeInputType): [Box]
boxItems(boxItemUuid: UUID!, page: Number, pageSize: Number): BoxItems
}
Which is then called by client like:
query BoxesQuery($input: SomeInputType){
boxes(input:$input){
boxItems:(pageSize:1){
total
}
}
}
In this case a boxItems resolver function is still able to access boxItemUuid in the args object. My question is what if I decide to create input types for my boxItems Query type. For instance, lets say boxItemUuid was now defined in FilterInfo type
boxItems(pageInfo: PageInfo, filter: FilterInfo): BoxItems
How would I go about defining the query client BoxesQuery, to pass boxItemUuid as a field on the FilterInfo type? Is this even possible? Is it bad practice for query types to include non scalar type parameters?

I didn't realize the resolver handler, which was not included in my question was checking parent, and args object for a particular parameter. So the answer here is to grab parameter from parent object
resolver(parent, args, context){
const boxItemUuid = parent.boxItemUuid || args.boxItemUuid;
}

Related

GraphQL register new Type wiring with argument to data fetcher

Having a GraphQL schema:
type TypeA {
id: ID,
name: String,
other: TypeC
}
type TypeB {
id: ID,
name: String,
other: TypeC
}
How should I implement TypeC wiring independently from source object type? I know I can do:
RuntimeWiring.newRuntimeWiring()
.type(TypeRuntimeWiring.newTypeWiring("TypeA")
.dataFetcher("other", dataFetcher_typeC.get())
.type(TypeRuntimeWiring.newTypeWiring("TypeB")
.dataFetcher("other", dataFetcher_typeC.get())
.build()
but then the data fetcher is dependant on a source object type:
DataFetcher<CompletableFuture<Collection<TypeC>>> get() {
return dataFetchingEnvironment -> {
<??> sourceObj = dataFetchingEnvironment.getSource();
return getObject(sourceObj.someProperty);
};
}
Given both POJOs (TypeA and TypeB) have reference field to TypeC, how to resolve TypeC field by given reference, not source object?
I have actually figured out two possible solutions to the problem:
When defining new wiring, get source object and from it the field. Call dataFetcher method with parameter, like regular java method:
Inside data fetcher get field name from DataFetcherEnvironment. Use reflection to get field from source object
Example #1:
RuntimeWiring.newRuntimeWiring()
.type(TypeRuntimeWiring.newTypeWiring("TypeA")
.dataFetcher("other", environment -> {
TypeA sourceObj = environment.getSource();
return dataFetcher_typeC.get(sourceObj.other)})
.type(TypeRuntimeWiring.newTypeWiring("TypeB")
TypeB sourceObj = environment.getSource();
return dataFetcher_typeC.get(sourceObj.other)})
.build()
Example #2:
DataFetcher<CompletableFuture<Collection<TypeC>>> get() {
return dataFetchingEnvironment -> {
Field declaredField = dataFetchingEnvironment.getSource().getClass()
.getDeclaredField(dataFetchingEnvironment.getField().getName());
declaredField.setAccessible(true);
String value = (String) declaredField.get(dataFetchingEnvironment.getSource());
return getObject(sourceObj.someProperty);
};
}
Second option looks better but still unsure if this is correct approach.
From the documentation here
the dataFetchingEnvironment provides getExecutionStepInfo() method which returns the ExecutionStepInfo object. From there, you can get the parent information.
ExecutionStepInfo executionStepInfo = environment.getExecutionStepInfo();
ExecutionStepInfo parentInfo = executionStepInfo.getParent();
GraphQLObjectType parentType = (GraphQLObjectType) parentInfo.getUnwrappedNonNullType();
// parentType.getName() returns you "TypeA" or "TypeB"

How to access query path properties in a resolver? GraphQL

I have a database with the following structure.
I'm writing a GraphQL resolver for the bottom-most node (the "rows" node).
As the image shows, each "rows" node corresponds to a specific path. (Company)->(DB)->(Table)->(rows)
A Query would be of the form:
{
Company(name: "Google") {
Database(name: "accounts") {
Table(name: "users") {
rows
}
}
}
}
Question: How can I include/access Company.name, Database.name, Table.name information in the rows resolver so that I can determine which rows node to return?
In other words: I know I can access Table.name using parent.name, but is there a way to get parent.parent.name or parent.parent.parent.name?
If there isn't a way to access ancestor properties, should I use arguments or context to pass these properties manually into the rows resolver?
Note: I can't use the neo4j-graphql-js package.
Note: This is the first simple example I thought of and I understand there are structural problems with organizing data this way, but the question still stands.
You can extract the path from the GraphQLResolveInfo object passed to the resolver:
const { responsePathAsArray } = require('graphql')
function resolver (parent, args, context, info) {
responsePathAsArray(info.path)
}
This returns an array like ['google', 'accounts', 0, 'user']. However, you can also pass arbitrary data from parent resolver to child resolver.
function accountResolver (parent, args, context, info) {
// Assuming we already have some value at parent.account and want to return that
return {
...parent.account,
message: 'It\'s a secret!',
}
}
function userResolver (parent, args, context, info) {
console.log(parent.message) // prints "It's a secret!"
}
Unless message matches some field name, it won't ever actually appear in your response.

How to pass different types as struct{} to function in GoLang?

I want to write a function that takes different struct-types as 1 parameter. Also, I have to be sure, that in these structs is an Id field. So I want a function like this:
MyFunction(object *struct{ Id int })
I tried it with passing the struct as a *struct{ Id int } and an interface{} parameter.
For example, I have these 2 struct-types:
type TableOne struct {
Id int
name string
date string
}
type TableTwo struct {
Id int
address string
athome bool
}
To save them in the database (using reflection) I have the following function:
func SaveMyTables(tablename string, obj *struct{ Id int }) {
// ... Some code here
if obj.Id != 0 {
// ... Some code here
}
// ... Some code here
}
I call the function like this:
obj := &TableTwo{
Id: 5
address: "some address"
athome: false
}
myPackage.Save("addresses", obj).
But I get this error:
cannot use obj (type *mytables.TableTwo) as type *struct { Id int } in argument to myPackage.Save
I want to write a function that takes different struct-types as 1 parameter. Also, I have to get sure, that in these struct is an Id field.
As of the current version of Go, you cannot do this. The only way Go supports passing multiple argument types to a single parameter is through the use of interfaces, and interfaces can only specify method sets, not fields.
(Go 2 plans to add generics, and this may be possible then. However, there's no concrete timeline for when that will be available.)

Graph QL, what does "on" do for a Fragment

I am looking at GraphQL but am confused why when using a fragment as below, you have to define the "on Character"? could this be anything any name as doesn't explain or have the context on the GraphQL documentation.
query {
leftComparison: hero(id: "1") {
...comparisonFields
}
rightComparison: hero(id: "2") {
...comparisonFields
}
}
fragment comparisonFields on Character {
name
appearsIn
friends {
name
}
}
While the example on graphql.org doesn't make this totally obvious, a fragment is always attached to some specific type (can be an object type, interface, or union). Inside the fragment, you can only use fields that exist on the type that's named; the server will check this for you (and clients are capable of checking ahead of time if they want to).
If a field returns an interface or union type, you can similarly only select fields that you know to exist (because an interface provides them), but you can attempt to match on specific types that implement the interface or are members of the union to get more data. This is frequently done with inline fragments, but since a named fragment is attached to a type, you can use named fragments as well. If the schema contains the very generic query
interface Node { id: ID! }
type Query {
node(id: ID!): Node
}
and Character implements Node, then you can plug in the named fragment you have here
query GetCharacterDetails($id: ID!) {
node(id: $id) {
...comparisonFields
}
}

How do I check if a outer type is a type of inner type?

If I have different forms of user structs being passed around my application is there a way to check if that embedded struct is a type of the outer struct?
type (
user struct {
name string
email string
}
admin struct {
user
level string
}
)
Depending on you need, you have two main methods: reflect.TypeOf, and the type swtich.
You will use the first to compare the type of an interface with another one. Example:
if reflect.TypeOf(a) == reflect.TypeOf(b) {
doSomething()
}
You will use the second to do a particular action given the type of an interface. Example:
switch a.(type) {
case User:
doSomething()
case Admin:
doSomeOtherThing()
}

Resources