Hi, a question about queries in Prisma: A User can...
# orm-help
f
Hi, a question about queries in Prisma: A User can have many Posts. How would we show a list of users and their total number of Posts?
users { id posts { id } }
and then counting
user.posts.length
in the frontend would work, but we cannot sort users by post amount from DB if we have pagination, right? I think requesting
users { id postsConnections { aggregate { count } } }
or similar is not supported by Prisma (in one single request), and if it was probably we cannot order by that in the same request. Another solution would be adding a
totalPosts
counter to the user and increment it every time a user writes a post, but atomic increments are not supported either so there could be issues with this as well. Therefore, what’s the recommended way to do this?
j
If you're using a server in front of Prisma you can add a field to the type with a custom resolver that basically runs
ctx.prisma.postConnection({where: { someIdField: parent.id }}).aggregate.count
something like that? P.S. I'm not 100% on the syntax there - but that's the general gist.
f
@Jenkins that would work to show the post number but I think there are two issues: I might be wrong on this but I think it makes 1 request to get N users and then N request to count posts. Also, I don’t think it’s possible to add pagination and sort by this field 🤔
j
You're right... Yeah, I would probably make a feature request for this on GitHub. That way it'll either be added as a feature or you'll get an explanation for why it's not doable.
f
I think there are feature requests for all of this already. I just want to know what’s the recommended workaround for now. Perhaps @marcus or @divyendu have some advice?
j
Possible! Their experience is a little higher than mine 😛
m
I think the proposal for the number of posts by @Jenkins looks good. And that should be 1 request in my opinion. Right now i don’t see why this should be N requests. @Fran Dios: Then you mention pagination and sorting by this field. I am not sure i understand you correctly. Do you basically want to sort the users by their number of posts? Yes this is a feature we are lacking at the moment. In this case you probably fallback to the raw access API.
But here’s another solution that could enable your idea for `totalPosts`: 1. I guess you are calling
createPost
in your application at some point. Inside this mutation you probably call a nested connect to the user for that Post. 2. My suggestion is to also update that
User
in the same mutation. The
User
should have a field
lastPost: DateTime!
. Set that time to the current time. 3. Have a cronjob in the background that runs every few minutes. This cronjob can query all users that have a
lastPost
greater than the last time it ran. Recompute the
totalPosts
property for all users returned by that queries and write it to the users.
So my 2nd proposal is a solution that is eventually consistent. The
totalPosts
property might be out of date when you query. If your cronjob runs it is up-to-date again. Sounds good to me for your usecase. I guess your users won’t post lots of posts all the time. So that counter is off by max 1 for a few minutes.
f
@Jenkins Thanks for your help! @marcus If I understood correctly how it works, the main resolver “getUsers” would do
return db.query.users()
. Then, I will have a “computed”
User.totalPosts
field only in my API, not in my DB, and add a resolver for this field which basically does
return db.query.postsConnection({ author: { id: "xxx" }, '{ aggregate { count } }')
. Doesn’t this create 1 request for
query.users
and many requests for
query.postsConnection
(one per user)? Or is it batched somehow?
Talking about the first solution here ^
About the second one, yes, it would definitely work, but honestly I’d prefer to stay away from cronjobs where a query should work. I guess raw access or using
pg
would work for us as well. This is just a toy example with User+Post to make it easier. In any case, thank you for taking the time @marcus
m
Regarding the first one: Ah yeah that would indeed be the case. I missed that part. I would not add this field to your application
User
type. I would add a new toplevel query field to your schema
totalPosts
which allows you to retrieve those counts for multiple users at once.
The second solution also has the advantage that the posts count is cached. And i guess your application is more read heavy.
f
totalPosts
which allows you to retrieve those counts for multiple users at once.
How would be the query to Prisma in that case? I thought we would need a “group by user id” in order to make this in 1 request?