Should I write two times each objects as 'input' and 'type' in a graphql schema file - graphql

I have to use a Java object in GraphQL in response as well as in request.
Should I have to write two times each objects as 'input' and 'type' in a GraphQL schema file? For getting that object in request as well as in response.
Should I define the same object two times with input and type?
file: test.graphqls
input Employee {
id: Integer
name: String
dept: String
active: String
}
type Employee {
id: Integer
name: String
dept: String
active: String
}

Yes, because the type system rules are very different for input and output types. Input types can not be unions, can not implement interfaces etc, so you can not simply use the same definition for both purposes.
Moreover, you must give each type a unique name. So it should be Employee and EmployeeInput for example.

Related

Architecture for avoiding repeated data in GraphQL

I have a application where the same data is present in many places in the graph and need to optimize the data queries to avoid processing and sending the same data too often.
As an example consider the following pseudo schema:
type Group {
name: String
members: [Person]
}
type Person {
name: String
email: String
avatar: Avatar
follows: [Person]
followedBy: [Person]
contacts: [Person]
groups: [Group]
bookmarks: [Bookmark]
sentMessages: [Message]
receivedMessages: [Message]
}
type Message {
text: String
author: Person
recipients: [Person]
}
type Bookmark {
message: Message
}
Querying a users data can easily contain hundreds, if not thousands, of Person-objects even though it the small circle of friends/contacts/follows only contains tens of distict users.
In my real implementation about 80% of each GraphQL query (in bytes) is redundant and considering that the client does many different queries in the same space above 90% of all data transferred and processed is redundant.
How could I improve the model so that I don't have to load the same data again and again without complicating the client too much?
I'm using Apollo for both GraphQL client and server.
Use/implement pagination (instead of just arrays) for relations - this way you can query for count/total (render it without array processing) and array of ids only - usually there is no need to query/join person table (DB) at all.
Render list of Person components (react?) using passed id prop only ... only rendered Person fetches for more details (if not cached, use batching to merge requests) consumed/rendered inside.

How to query in GraphQL with no fixed input object contents?

I want to query to get a string, for which I have to provide a input object, however the input data can have multiple optional keys and quite grow large as well. So I just wanted something like Object as data type while defining schema.
// example of supposed schema
input SampleInput {
id: ID
data: Object // such thing not exist, wanted something like this.
}
type Query {
myquery(input: SampleInput!): String
}
here data input can be quite large so I do not want to define a type for it. is there a way around this?

Type error with Hasura array data type: "A string is expected for type : _int4"

I have a table I created in the Hasura console. A few of the columns are integer int types and I get the expected data type: Maybe<Scalars['Int']>.
However, a few needed to be an array of integers so I created those in the Hasura SQL tab:
ALTER TABLE my_table
add my_ids integer[];
If I populate those in GraphiQL with the following query variable everything works just fine:
{
"my_ids": "{1200, 1201, 1202}",
}
However, when I try to make the same request from my front-end client, I received the following error: A string is expected for type : _int4. Looking at the datatype, it is slightly different than the preset (in the data type dropdown) integer types: Maybe<Scalars['_int4']>.
Is there a way to get the array of integers to be Maybe<Scalars['Int']> like the preset integer types? Or if there isn't, how can resolve the issue with my request throwing errors for this _int4 type?
Hasura cannot process array but it can process array literals.
I've written a function to help you to transform your array into array literal before mutation:
const toArrayLiteral = (arr) => (JSON.stringify(arr).replace('[', '{').replace(']', '}'))
...
myObject.array = toArrayLiteral(myObject.array) // will make ['friend'] to {'friend'}
Good luck

Properly handling gRPC types to SQL ORM

I'm implementing a gRPC server and using an ORM called Boiler for Go. I've gotten to a point where I've built all my models and protos and now I'm handling specific type issues.
Within my protobuf files I've declared most types as strings. However my ORM treats (due to how it interfaces with Postgres) strings as null.String in it's models. Hence when I attempt something like so I get an error:
user := &models.User{
FirstName: req.FirstName,
LastName: req.LastName,
Email: req.Email,
Gender: req.Gender,
PhoneNumber: req.PhoneNumber,
}
The error: services/users.go:46:3: cannot use req.FirstName (type string) as type null.String in field value
The question is what would be the most appropriate way of handling this situation. I could: generate a new struct (which I'm already using for data validation) and cast them into null.String or I suppose I could attempt to force the casting somehow?
The question then becomes if a user doesn't supply a value in the API and the validation process allows it, how would that handle the non-existing record?
Edit: Seems like SQLBoiler developers have a package for handling nulls separately. ie. null.StringFrom(), null.Int15From etc. which I'd in essence wrap all my fields with as such:
user := &models.User{
FirstName: null.StringFrom(req.FirstName),
LastName: null.StringFrom(req.LastName),
Email: null.StringFrom(req.Email),
Password: string(password_hash),
Role: "BASIC_USER",
Status: "ACTIVE",
Gender: null.Int16From(req.Gender),
PhoneNumber: null.StringFrom(req.PhoneNumber),
VerificationCode: null.StringFrom(code.String()),
}
Feels kind of dirty but I don't see any other options. Suggestions/opinions anyone?

Is it a bad practice to use an Input Type for a graphql Query?

I have seen that inserting an Input Type is recommended in the context of mutations but does not say anything about queries.
For instance, in learn tutorial just say:
This is particularly valuable in the case of mutations, where you might want to pass in a whole object to be created
I have this query:
type query {
person(personID: ID!): Person
brazilianPerson(rg: ID!): BrazilizanPerson
foreignerPerson(passport: ID!): ForeignerPerson
}
Instead of having a different type just because of the name (rg, passport) of the fields, or put one more argument like type in query, I could not just have the Person with an documentNr field and do an Input type like that?
input PersonInput {
documentNr : ID!
type: PersonType # this type is Foreign or Brazilian and with this I k
}
PersonType is a enum and with him I know if the document is a rg or a passport.
No, there is nothing incorrect about your approach. The GraphQL spec allows any field to have an argument and allows any argument to accept an Input Object Type, regardless of the operation. In fact, the differences between a query and a mutation are largely symbolic.
It's worth pointing out that any field can accept an argument -- not just ones at the root level. So if it suited your needs, you could easily set up a schema that would allow queries like:
query {
person(id: 1) {
powers(onlyMutant: true) {
name
}
}
}

Resources