If you use:
const tasks = await ctx.db
.query("tasks")
.filter((q) => q.eq(q.field("isCompleted"), true))
.take(5);
Convex will scan documents in the "tasks" table one by one, applying the filter, and will stop scanning once it has found 5 documents that match isCompleted: true. However, if there are very few matching documents or they are near the end of the table, Convex may need to scan many (or even all) documents to find those 5 matches. So, while .take(5) limits the number of results returned, it does not necessarily limit the number of documents scanned if the filter is not supported by an index.
From the documentation:
This document query will not scan more than 5 documents.
const tasks = await ctx.db.query("tasks").take(5);
On the other hand, this document query:
const tasks = await ctx.db
.query("tasks")
.filter((q) => q.eq(q.field("isCompleted"), true))
.first();
might need to walk over every single document in the "tasks" table just to find the first one with isCompleted: true Querying performance and limits.
The same logic applies to .take(5) after a filter: it will scan until it finds 5 matches, which could mean scanning the whole table in the worst case. To avoid this, you should use an index on the isCompleted field if you expect many documents and want to optimize performance and bandwidth usage.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: