Query documents by array of documentIds possible?
Is there any way to get the documents by array of documentIds?
here I'm querying my documentIds in array!
const collaborators = await ctx.db
.query("collaborators")
.withIndex("by_email", (q) => q.eq("email", args.email))
.collect();
const documentIds = collaborators.map(collaborator => collaborator.document);
Now I want to query all the documents whose _id presents in documentIds array!12 Replies
const documents = await Promise.all(
documentIds.map(async (id) => {
return await ctx.db.get("documents", id);
})
);
this should workI tried this one but I'm wondering if there are any inbuild convex queries to do so!
you can use filter from convex helpers then to directly filter "documents"
Using TypeScript to Write Complex Query Filters
There’s a new Convex helper to perform generic TypeScript filters, with the same performance as built-in Convex filters, and unlimited potential.
i would say
Promise.all
is the built-in convex way to do it. under the hood it queues up all of the db.get
requests on the js microtask queue, and then when you await them all together it does a batched fetch with the by_id
index.
(by contrast, filter
scans the whole table, which is probably less efficient)That's great point @lee
So 1 or 2?
1. filter from helpers!
const documents = await filter(ctx.db.query("documents"), (document) =>
documentIds.includes(document._id)
).collect();
2. Promise.all() by Javascript !!
const documents = await Promise.all(
documentIds.map(async (id) => {
return await ctx.db.get(id);
})
);
👀 ??
1st one will have n db quires depending on length of documentIds array!
2nd one has only one query to DB but 2 heavy tasks 1stly fething all the documents in one go may be there are thousands and 2ndly filtering on that n number of documents!!
Bit confused here!1st one will have n db quires depending on length of documentIds array!no, the first one is equivalent to
Oh sorry I mean 2nd one swap the content please for both the points!!
ah true
i would always do the 2nd one. it's almost always going to be more efficient. the only time the 1st would be more efficient is if the set of document ids is on the same order of magnitude as the full "documents" table.
That's cool thanks @lee
btw this is one of the things i like about convex: we let you pick the query plan. i've fought with mysql and postgres where i give a query like
SELECT document FROM documents WHERE id IN (1, 2)
and it says "i think it will be faster to scan the entire documents
table than look up 2 documents via the index on the id
column." And then my query's performance plummets. in Convex that won't happen; you can tell it to do a table scan or you can ask it to do 100 point lookups; it won't decide and in particular it won't make the wrong decision.