GraphQL multiple queries in one request - graphql

I have some groups created by users in my database. Each group has multiple members in it. This is what a typical group looks like:
{
"groupName": "some-group-name",
"userIds": ["001", "002", "003"]
}
I also have a separate node of users in my database. This is what a user looks like:
{
"id": "001",
"userName": "some-unique-username"
}
I want to list every single group and its members. So, it would be:
group1
user1 id; user1 name;
user2 id; user2 name;
group2
user3 id; user3 name;
user4 id; user4 name;
and so on...
How would it be possible (if at all) to fetch these groups and their user ids and also query for users by id and return a single JSON containing all the data only with one request?
Right now I'm just fetching some amount of groups and iterating over the userIds of each of them and sending a request for each user separately.
I'm not asking about pagination or simple querying, I just want to get every group and the users inside those groups.

Figured it out myself.
What I needed to do was to create a separate resolver for fetching members of each group:
resolvers: {
...
Group: {
members: (group, _, context) => group.members.map(memberId => context.db.findUserById(memberId)
}
...
}
The parent group object is passed as the first argument to the resolver so when I query:
{
groups(count: 10){
name
members {
name
}
}
}
It returns the names of the first 10 groups along with its members' names.

With the following schema,
type User {
name: String
firstName: String
location: String
}
type Group {
groupname:String!
users:[User!]
}
type Query {
groups:[Group!]
group(name: String): Group
}
the following query:
{
groups
{
groupname
users {
name
firstName
location
}
}
}
could return
{
{ name: "group1",
users: [{name:"user1", firstName:"firstName1", location:"Localtion1"},
{name:"user2", firstName:"firstName2", location:"Localtion2"}]
},
{ name: "group2",
users: [{name:"user1", firstName:"firstName1", location:"Localtion1"}]
},
...etc..
}
Hope this helps,

Related

Custom type replacement with Hot Chocolate 12

My schema defines an Employee type that has 15 or so fields on it. It's then used multiple times in other areas:
type Employee {
active: Boolean!
name: String
id: Int!
...
}
type Room {
owner: Employee!
delegate: Employee
}
99% of the time, I want the same three fields when returning data on an employee. So I end up writing a query like this:
query {
rooms {
owner: {
name
id
active
}
}
}
which is repetative when something has multiple employees. Is there a way to define some type of transformation so that instead I'd do something like:
query {
rooms {
owner: #commEmpFields
}
}
My initial thought was to create a custom ObjectType<Employee> but then I realized that I didn't know how to map that to the query.

Querying Many-To-Many Relationships in AWS Amplify

I have two models in my graphql schema and the one I am trying to query on, Sessions, has two #belongsTo directives (read on a forum this matters). I can successfully save these models and view them on the AWS AppSync Queries Tab where I can query getSessions successfully BUT when I try to the exact same query locally following these docs:
(https://docs.amplify.aws/lib/graphqlapi/advanced-workflows/q/platform/flutter/#combining-multiple-operations)
I get an error locally:
type "Null" is not a subtype of type 'string'
What am I doing wrong and how do I fix this so I can successfully retrieve my nested query:
Here are my models as a reference:
Sessions:
type Session
#model
#auth(
rules: [
{ allow: public }
{ allow: owner }
{ allow: groups, groups: ["Admin"] }
]
) {
id: ID!
name: String
numPeoplePresent: Int
notes: String
eIdReader: String
weighTiming: String
cows: [Cow] #manyToMany(relationName: "CowSession")
proceduresID: ID
procedures: Procedures #hasOne(fields: ["proceduresID"])
}
Cow:
type Cow
#model
#auth(
rules: [
{ allow: public }
{ allow: owner }
{ allow: groups, groups: ["Admin"] }
]
) {
id: ID!
name: String!
RfId: String
weight: [Float!]!
temperament: [Int]
breed: String
type: String
dateOfBirth: AWSDate
sessions: [Session] #manyToMany(relationName: "CowSession")
procedures: [Procedures] #manyToMany(relationName: "CowProcedures")
}
This is the query that is causing the error:
const getSession = 'getSession';
String graphQLDocument = '''query getSession(\$id: ID!) {
$getSession(id: \$id) {
numPeoplePresent
notes
name
eIdReader
id
owner
proceduresID
updatedAt
weighTiming
cows {
items {
cow {
RfId
}
}
}
}
}''';
final getSessionRequest = GraphQLRequest<Session>(
document: graphQLDocument,
modelType: Session.classType,
variables: <String, String>{'id': sessID}, //parameter of the current session can hardcode to whatever you need here
decodePath: getSession,
);
final response =
await Amplify.API.query(request: getSessionRequest).response;
print('Response: ${response.data}');
The wonderful people at amplify answered this quickly so I will relay the information here:
the problem was the intermediary ids were not included in my local query so it was unable to retrieve the nested Cows. Updated query looks like this:
getSession = 'getSession';
String graphQLDocument = '''query getSession(\$id: ID!) {
$getSession(id: \$id) {
numPeoplePresent
notes
name
eIdReader
id
owner
proceduresID
updatedAt
weighTiming
cows {
items {
id <-- needed this one
cow {
id <-- and this id too
RfId
breed
dateOfBirth
name
type
weight
}
}
}
}
}''';

Prisma many to many relations Query

I have a User model along UserRelationship model
I have created trainer/client relationship with the UserRelationship model.
model User {
id Int #id #default(autoincrement())
trainerRelationship UserRelationship[] #relation("trainer")
traineeRelationship UserRelationship[] #relation("trainee")
}
model UserRelationship {
id Int #id #default(autoincrement())
trainerId Int?
traineeId Int?
trainerUser User? #relation("trainer", fields: [trainerId], references: [id])
traineeUser User? #relation("trainee", fields: [traineeId], references: [id])
}
I am able to query the user also able to query their relationship
For eg:
const trainer = await client.user
.findUnique({ where: { id }, include: { trainerRelationship: true } })
The output i am getting here is like:
{
id: 1,
username: hellouser
trainerRelationship: [
{
id: 4,
trainerId: 1,
traineeId: 34
}
]
}
Now i want to fetch the details of the traineeId/trainerId user details, What should be my query?
Ok, so I have solved it by the below query, incase someone is stuck:
.findUnique({ where: { id } }).trainerRelationship({
include: {
trainerUser: true,
},
})

How to make self resolving array of object types with Prisma and GraphQL

Maybe the title is not accurate but I really don't know how to describe it anymore. I went through multiple documentations and descriptions but still couldn't figure it out.
I want to implement a basic social media like followers/following query on my type User. I am using MySQL and for that I made a separate table called Follow as it's a many-to-many connection.
Here is a pseudo-ish representation of my tables in the database without the unnecessary columns:
Table - User
user_id primary key Int
Table - Follow
follow_er foreign_key -> User(user_id) Int
follow_ed foreign_key -> User(user_id) Int
A user could "act" as a follow_er so I can get the followed people
And a user could be follow_ed, so I can get the followers.
My prisma schema look like this:
model User {
user_id Int #id #default(autoincrement())
following Follow[] #relation("follower")
followed Follow[] #relation("followed")
}
model Follow {
follow_er Int
follower User #relation("follower", fields: [follow_er], references: [user_id])
follow_ed Int
followed User #relation("followed", fields: [follow_ed], references: [user_id])
##id([follow_er, follow_ed])
##map("follow")
}
By implementing this I can get the followers and following object attached to the root query of the user:
const resolvers = {
Query: {
user: async (parent, arg, ctx) => {
const data = await ctx.user.findUnique({
where: {
user_id: arg.id
},
include: {
following: true,
followed:true
}
})
return data
}....
Here is my GraphQL schema I tried to make:
type Query{
user(id: Int!): User
}
type User{
id: ID
following: [User]
followed: [User]
}
So I can get something like:
query {
user(id: $id) {
id
following {
id
}
followed{
id
}
}
}
}
But I couldn't make it work as even if I get the the array of objects of {follow-connections}:
[
{
follow_er:1,
follow_ed:2
},
{
follow_er:1,
follow_ed:3
},
{
follow_er:3,
follow_ed:1
},
]
I can't iterate through the array. As far as I know, I have to pass either the follow_er or follow_ed, which is a user_id to get a User object.
What am I missing? Maybe I try to solve it from a wrong direction. If anybody could help me with this, or just tell me some keywords or concepts I have to look for it would be cool. Thanks!
I would suggest creating self-relations for this structure in the following format:
model User {
id Int #id #default(autoincrement())
name String?
followedBy User[] #relation("UserFollows", references: [id])
following User[] #relation("UserFollows", references: [id])
}
And then querying as follows:
await prisma.user.findUnique({
where: { id: 1 },
include: { followedBy: true, following: true },
})
So you will get a response like this:

Graphql syntax for single query for same field with different parameters from an array

I am looking for something like the below pseudo query:
query users($ids: [String!]) {
"id from $ids": getUser(id){
id
name
dob
}
}
To get a response like:
data: {
'039ccf5c-3070-4368-b790-0884669e759d': {id: '039ccf5c-3070-4368-b790-0884669e759d', name: 'u1', 'dob': 12-12-12'},
'139ccf5c-3070-4368-b790-0884669e759d': {id: '139ccf5c-3070-4368-b790-0884669e759d', name: 'u1', 'dob': 12-12-12'},
}
Is this possible?
You can use aliases to query to the same field multiple times:
query users($id1: String!, $id2: String!) {
user1: getUser(id: $id1) {
...UserFragment
}
user2: getUser(id: $id1) {
...UserFragment
}
}
fragment UserFragment on User {
id
name
dob
}
There are no control structures in GraphQL, so there's no way to loop through a value that is a list. If your list of IDs is of variable length, then you'll have to construct a query similar to the above programmatically, dynamically generating both the variable definitions and the aliased fields.

Resources