```const followedUser = await context.prisma.follo...
# orm-help
n
Copy code
const followedUser = await context.prisma.followUser.upsert({
  where: { followerId: 4, followingId: args.userId },
  update: { status: args.status },
})
m
Hey. Is it not working for you?
Copy code
const followedUser = await context.prisma.followUser.upsert({
  where: { followerId: 4, followingId: args.userId },
  update: { status: args.status },
  create: {
     followerId: 4, 
     followingId: args.userId,
     status: args.status
  }
})
n
yeah. am i doing this right?
Argument where of type FollowUserWhereUniqueInput needs exactly one argument, but you provided followerId and followingId. Please choose one. Available args:
export type FollowUserWhereUniqueInput = { followerId?: number followingId?: number }
this is in the prisma client. index.d.ts
m
Ok I see.
upsert
works like
findUnique
So you only can use one variable in the where clause to find an unique record. So you can remove on of those ids in the where clause:
Copy code
const followedUser = await context.prisma.followUser.upsert({
  where: { followingId: args.userId },
  update: { status: args.status },
  create: {
     followerId: 4, 
     followingId: args.userId,
     status: args.status
  }
})
That's beacase if you have
followerId
on FollowUser marked as
@unique
there will be no other records in that table with that same
followerId
. The same goes for
followingId
n
yes. yes. that make sense. Thank you so much. @Maciek K
👍 1
n
@@unique([followerId, followingId])
yeah. im grind my head around this. and i think both followerId and following id shoud both be evaluated?
m
Remember to add a name to that compound unique
Copy code
@@unique(fields: [followerId, followingId], name: "myCompoundUniqueName");

const followedUser = await context.prisma.followUser.upsert({
  where: { myCompoundUniqueName: { followerId: 4, followingId: args.userId } },
  update: { status: args.status },
  create: {
     followerId: 4, 
     followingId: args.userId,
     status: args.status
  }
})
Does that work?
Other way that compound name will default to
followerId_followingId
Sidenote: I didn't evaluate it your schema is correct for your use case. But from a quick glimpse and if I understand it correctly, it looks like you should ditch those
@unique
attributes from
followerId
and
followingId
. Because that way if you create one FollowUser with a
followerId
, then you won't be allowed to create more in this table with that
followerId
. The same goes for
followingId
.
n
now prisma is asking me there should be one argument in the where clause of the upsert
m
See how I have defined the where clause
You should use the compound unique name in the where clause
Copy code
const followedUser = await context.prisma.followUser.upsert({
  where: { followerId_followingId: { followerId: 4, followingId: args.userId } },
  update: { status: args.status },
  create: {
     followerId: 4, 
     followingId: args.userId,
     status: args.status
  }
})
n
this works defintely as aspected. but why the red lines
i did generate the client also
m
I don't know, what does the linter say?
n
Type ‘{ followerId_followingId: { followerId: number; followingId: number; }; }’ is not assignable to type ‘FollowUserWhereUniqueInput’. Object literal may only specify known properties, and ‘followerId_followingId’ does not exist in type ‘FollowUserWhereUniqueInput’.ts(2322)
something like this.
m
Hmm I don't know 🙂 Can't help you with that, but glad it works 🙂
n
Copy code
const followingUsers = await context.prisma.user.findMany({
  include: { following: true },
  skip: args.offset || undefined,
  take: args.limit || undefined,
})
i was wondering the other way around. how can bring followers and followings.
im sure my query doesnt make any sense. becuase including will bring all
m
What do you actually want to query?
n
to get all the users the auth user is following. and people who follows him.
if the auth user’s id is 4. auth user user is following the the userid 8
becasue the status is 1
but user8 is not following auth user
beause status is 0
am i doing this the most complicated way?
but my goal here is being able to follow a user and to fetch followers and follwings for a given user
m
Yeah if thats a 0 1 (false, truth) if somebody follows you, I think you don't need that status. Existence of that row in the FollowUser table is enough. You would just need to delete whole record from FollowUser if somebody unfollows. Then you want to search like this:
Copy code
await context.prisma.user.findMany({
  where: {
    OR: [
     { followedBy: { followingId: authorizedUserId },
     { following: { followerId: authorizedUserId },
    ],
   }
});
That will get you all followers and all following in one query.
Try if it works for you
Other aproach:
Copy code
await context.prisma.user.findUnique({
  where: {
    id: authorizedUserId,
  },
  include: {
    followers: {
      include: {
        follower: true,
      },
    },
    following: {
      include: {
        following: true,
      }
    }
  }
})
Btw since you're using Nexus. If you have set up properly your relations in Nexus, you can just query your graphql server from frontend like:
Copy code
query USER_WITH_RELATIONS($id: ID!) {
   user(id: $id) {
     id
     // firstName
     // lastName
     followedBy {
       follower {
         id
         // firstName
         // lastName
       }
     }
     following {
       following {
         id
         // firstName
         // lastName
       }
     }
   }
 }
n
i see, status is important because i have toggle followUser function in my client. but if i remove the status field. the followUnfollow toggle request from a client would result in creating a record if it does not exist or delete the record if it exist. and from prisma i’d have to manually do the creating and deletion mutations. and getting followers and following. i accually want to get full paginated list of followers and following from the followUser table instead of user table beacuse i don’t want to have the user object in the query
query GetFollowers($limit: Int, $offset: Int) { getFollowers(limit: $limit, offset: $offset) { id name } }
m
Yes, that's what you would want to do: create a record if doesn't exist and delete if exists. Other way you're having reduntant data. There's no use of a record with status: false. That's a relation table. Only use case I can think of is if you want to 'remember' the first follow from
createdAt
. But you don't need that. If you still want to have the status then you would want to just add it to the where clause. And if you want to query the followUser table:
Copy code
const followersAndFollowing = await context.prisma.followUser.findMany({
  where: {
    status: true,
    OR: [
      {followingId: authenticatedUserId },
      {followerId: authenticatedUserId}
    ]
  },
  include: {
    follower: true,
    following: true,
  }
})
Altought that way you will probably need to map that array later to get a list of followers and followings. You would want to split that to two queries: for followers and followings.
Copy code
const followers = await context.prisma.followUser.findMany({
  where: {
    status: true,
    followingId: authenticatedUserId 
  },
  include: {
    follower: true,
  }
})
Add the pagination if you want. Hope it helps.prisma rainbow