Hi how can we get documents based on a
Hi, how can we get documents based on a list of id;s that it should match
export const getUsers = query({
args: {
userIds: v.array(v.string()), //list of userId's that I want to check and retrieve
},
handler: async (ctx, args) => {
const users = await ctx.db
.query('users').filter((q) => q.eq(q.field('userId'), args.userIds)) //get all the users, who match the userID
.collect();
return users;
},
});
9 Replies
For a short list you can use the
.or()
filter method. For longer lists (but not too long, unsure what the ideal upper bound is), you can loop over an array and make a separate call for each user. Or you can combine these two and use .or()
with chunks of an array of user ids.
I'm just a community member, Convex team may have better ideas.
.or()
filter method docs: https://docs.convex.dev/api/interfaces/server.FilterBuilder#orDoing a filter with
or()
will scan the whole table (which works but is inefficient). If you want to look up each user you would do db.get(userId)
and to look them all up you can do await Promise.all(userIds.map((userId) => db.get(userId)))
Isn't this way too costly?
What do you mean by too costly? If you're looking up a bunch of documents by id, there are two ways to do it -- for the sql statement
SELECT * FROM users WHERE id IN (id1, id2, ...)
there are two possible query plans: it could scan the users table and apply the filter (better for small tables), or it could look up each user by id (better for large tables). In Convex these plans are represented by @erquhart 's suggestion and mine, respectively. I can't think of other query plans that would be less costly.@Papa Johns I have code snippets like the one Lee posted all over my convex backend, they're faster than you'd expect. No performance issues in my experience.
I was thinking to like have a utility function like
findOne
or findMany
or findUnique
etc. As using those function, one has to just provide the arugments only.findOne
and findUnique
are covered by the first()
and unique()
query methods, respectively. For findMany()
, you could pretty easily create your own helper using the above mentioned mapping function.what I wanted to acheive was, I have chats, and I want to pick up user profile picture, but with my current setup I am attaching image url for every message thats a lot....
and then ofc I need a userId to store on the message itself, and I am doing that, and what I was trying to do was create a user as I register them through clerk and then refer to that userID form convex and get all the users in the current chat and then get the image url from the Users in convex.
and the messages, I am doing a pagination, so its 20 at a time, and was thinking to some how get image urls based on the user ID on the message -> connecting to userId on the user table in convex.
You could send back user info on a per page basis too, happy medium
Maybe something like this in your paginated query:
But if you know there's not a ton of users in a channel, you could just fetch them all at the channel level and forego this as well.
Also worth mentioning that you can probably get pretty far before you actually need to do any of this. Returning the urls on each message is not ideal, but if you're early iterating on your product, it may be worth considering just letting it be if you're not experiencing a performance issue.