I have a CHAT_MESSAGE_FRAGMENT that returns all the message data from my Hasura graphql api.
However, the Gifted Chat react-native component requires the data in a specific structure so I'm attempting to convert it with the query below.
I'm able to alias all the top level data but can't figure out how to add a nested level of data.
I'm guessing it isn't possible but I thought I'd ask in case I'm missing something.
const GIFTED_CHAT_GROUP_MESSAGES_QUERY = gql`
query chatGroupMessages($chatGroupId: Int!) {
chat_message(
where: { to: { id: { _eq: $chatGroupId } } }
) {
_id: id,
# user: {
# _id: from.id, <== How do I add
# name: from.name, <== this secondary level?
# },
text: message,
image: image_url,
createdAt: created_at,
system: message_type,
}
}
${CHAT_MESSAGE_FRAGMENT}
`;
Assuming you already have chat_message.user_id -> users.id foreign key constraint set up, you'll also need to alias the from object in addition aliasing any of its nested fields:
const GIFTED_CHAT_GROUP_MESSAGES_QUERY = gql`
query chatGroupMessages($chatGroupId: Int!) {
chat_message(
where: { to: { id: { _eq: $chatGroupId } } }
) {
_id: id,
from: user: {
_id: id,
name
},
text: message,
image: image_url,
createdAt: created_at,
system: message_type,
}
}
${CHAT_MESSAGE_FRAGMENT}
`;
The secondary level of data is basically nested object queries in Hasura. You can nest any number of queries as long as a relationship has been created.
In this case, assuming the chat_message table has a user_id field, you can establish a foreign key constraint for chat_message.user_id -> users.id, where users is a table with id as primary key.
Once the foreign key constraint is created, Hasura Console automatically suggests relationships. Here user would be an object relationship in chat_message table.
Here's the official docs link for Creating a relationship
Related
In PHP Lighthouse you can have ManyToMany relationships. Using nested operations allows you to create say an Author, Post and connect them using a pivot table post_author ALL in one operation.
Lighthouse also allows you to store data in the pivot table. In their docs, they give an example of how to connect a record with some pivot table data. There is no example available on how to do a create operation with extra pivot table data.
Docs pivot data update operation: https://lighthouse-php.com/master/eloquent/nested-mutations.html#storing-pivot-data
type Mutation {
createPost(input: CreatePostInput! #spread): Post #create
}
input CreatePostInput {
title: String!
authors: CreateAuthorBelongsToMany
}
input CreateAuthorBelongsToMany {
create: [CreateAuthorInput!]
}
input CreateAuthorInput {
name: String!
#contribution_percentage: Int! #Pivot table column
}
#query:
mutation {
createPost(
input: {
title: "My new Post"
authors: {
create: [{ name: "Herbert", contribution_percentage: 50 }]
}
}
) {
id
authors {
name
}
}
}
I tried fiddling with the scheme to "guess" the correct scheme, to no avail.
My objective is: Create an Author, Post, and connect them using a post_author pivot table WITH extra pivot data, ALL in one operation.
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:
I am using appsync with amplify and trying to figure out how to query based on two different selectors. Basically I need to either query all if neither county or facility are supplied, query with county while facility is empty, or query with facility while county is empty. I thought I could wrap this into 1 query but it doesn't seem like I can. My appsync schemas look like this.
type Client
#model
#key(name: "clientByCountyOrFacility", fields: ["county", "facility"], queryField: "getClientsByCountyOrFacility")
#searchable {
id: ID!
facility: String!
county: String!
products: [Product] #connection(name: "ClientProducts")
}
type Product
#model
#searchable {
id: ID!
client: Client #connection(name: "ClientProducts")
}
I can get this to work by using (below query) but I am worried this will run into the 100 scan limit because it uses the listClients query underneath. Possibly if there was an easy way to change that could be a solution but it seems the files in amplify are autogenerated.
query getClientsByCountyOrFacility($county: String = "", $facility: String = "") {
listClients(filter: {
county: {
contains: $county
}
facility: {
contains: $facility
}
}) {
items {
id
products {
items {
id
}
}
}
}
}
I added the #key to see if I could create an index but it doesn't like that and I'm at a lose for how to acquire the data. How do I go about building this schema and query to get the data back?
I want to create 2 related objects, e.g. 1 Location and 1 Place where Place has a reference to Location like so:
type Location {
id: String
name: String
}
type Place {
id: String
locationId: String
}
Is it possible to do this with 1 mutation request? Currently I'm doing this with 2 separate mutation requests like below:
mutation ($locationName: String!) {
insert_Location(objects: {name: $locationName}) {
returning {
id
}
}
}
//in another request, use the id returned from the request above
mutation ($locationId: String!) {
insert_Place(objects: {locationId: $locationId}) {
returning {
id
}
}
}
I'm aware it's possible to have multiple fields in a mutation so I could create 2 Locations in 1 mutation request like below.
mutation ($locationName: String!) {
location1: insert_Location(objects: {name: $locationName}) {
returning {
id
}
}
location2: insert_Location(objects: {name: $locationName}) {
returning {
id
}
}
}
However if I wanted to do this to create 1 Location and 1 Place, is there a way to retrieve the created Location Id and pass it to the 2nd field to create the Place?
For future reference:
As #Xetera pointed out, because the 2 types have a foreign key relationship you can do a nested insert mutation where hasura would handle setting the foreign key value. In my case it would look something like:
mutation ($locationName: String!) {
insert_Place(
objects: {
Location: {data: {name: $locationName}}, //hasura will create Location and assign the id to Place.locationId
}
) {
returning {
id
}
}
}
Docs here for further reading: https://hasura.io/docs/1.0/graphql/manual/mutations/insert.html#insert-an-object-along-with-its-related-objects-through-relationships
I have some Laravel models that are related via a pivot table in a belongsToMany relation.
Now I try to create a mutation in Laravel Lighthouse to join the models and also fill the pivot values.
Somehow I cannot find out how to do this.
The Course model looks like this:
class Course extends Model
{
public function programs(): BelongsToMany
{
return $this->belongsToMany(\App\Models\Program::class, 'Course_Program')
->withPivot('id', 'year_id')
->withTimestamps();
}
}
My GraphQL code looks like this:
type Mutation {
createCourse(input: CreateCourseInput! #spread): Course! #create
}
type Course {
id: ID!
name: String!
programs: [ProgramWithPivot!]! #belongsToMany
}
type Program {
id: ID!
name: String!
}
type ProgramWithPivot {
id: ID!
name: String!
year_id: ID!
}
input CreateCourseInput {
name: String!
programs: CreateCourseProgramsRelation!
}
input CreateCourseProgramsRelation {
create: [CreateCourseProgramInput!]
}
input CreateCourseProgramInput {
id: ID!
year_id: ID!
}
The problem is that when I try to create programs in my course like this:
mutation {
createCourse(input: {
name: "new cours"
programs: {
create: [{
id: 1
year_id: 2
}]
}
}) {
id
programs {
id
year_id
}
}
}
Laravel Lighthouse tries to insert data into the Program table (and complains that Program.name does not have a default value).
However, I want to insert data (course_id, year_id and program_id) into the Course_Program table.
How do I tell Laravel Lighthouse to insert data in the pivot-table?
Mutating pivot data is currently not there, but I did a PR for this last week. You can follow the PR progress
In general it will be included either the way I did it, or maybe a little bit different. It was discussed in this issue
For now you can update your pivot data only using custom resolver/directive. But probably the best way will be just to wait till PR gets merged.
There is any way of doing update / upsert to pivot data via nested mutation?