#gf
15 messages · Page 1 of 1 (latest)
If you call .take(2) but there is only one document in the table, it will simply return that one document as an array with a single element. As the docs state, .take(n) returns:
"An array of the first
nresults of the query (or less if the query doesn't havenresults)."
So it won't throw an error — it just returns however many documents are available, up to the specified limit.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@tulip hazel Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@dapper oracle is there a way to just purge all documents in a table
Let me check the knowledge base for you again. One moment! :books:
Yes, there are a few ways to purge all documents in a table in Convex:
1. Dashboard (easiest)
You can use the Convex dashboard's "Clear Table" option — click the ⋮ overflow menu at the top of the data page and select "Clear Table". This deletes all documents without removing the table itself. [Clear a table]
Alternatively, "Delete Table" will remove all documents and the table itself. [Delete a table]
2. CLI one-liner
You can delete all documents in a table by importing an empty file in "replace" mode:
npx convex import --table $TABLE --replace --format jsonLines /dev/null
To clear every table at once:
for tableName in `npx convex data`; do npx convex import --table $tableName --replace -y --format jsonLines /dev/null; done
3. In code (mutation)
You can write a mutation that collects all documents and deletes them:
const docs = await ctx.db.query("myTable").collect();
await Promise.all(docs.map((doc) => ctx.db.delete(doc._id)));
⚠️ Note: This approach is limited to tables with fewer than ~4,096 documents in a single mutation due to Convex's read limits. For larger tables, you'd need to paginate and use scheduled/recursive mutations.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@tulip hazel Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@dapper oracle is it about for you to run a infiitely running scheduled mutation????
Let me check the knowledge base for you again. One moment! :books:
Yes, this is a well-supported pattern in Convex! A mutation can recursively schedule itself to run indefinitely (or until some condition is met). This is commonly used for things like batch processing, data migrations, and cron-like workflows.
Here's an example of a mutation that pages through a table and keeps scheduling itself until done:
export const myMigrationBatch = internalMutation({
args: { cursor: v.union(v.string(), v.null()), numItems: v.number() },
handler: async (ctx, args) => {
const data = await ctx.db.query("mytable").paginate(args);
const { page, isDone, continueCursor } = data;
for (const doc of page) {
// process doc
}
if (!isDone) await ctx.scheduler.runAfter(0, internal.example.myMigrationBatch, {
cursor: continueCursor,
numItems: args.numItems,
});
}
});
[Batching via recursive scheduling]
A few key points:
- Scheduled mutations are guaranteed to execute exactly once and are automatically retried on transient errors, making this pattern very reliable. [Scheduler interface]
- Using
ctx.scheduler.runAfter(0, ...)schedules the next run immediately after the current mutation commits. [Scheduled Functions] - Each individual mutation run has its own read/write limits, so you should keep each batch small (e.g. 500 documents at a time) to avoid hitting limits. [Read/write limit errors]
This is the recommended pattern for processing large datasets in Convex — keep each mutation light and let the scheduler chain them together.
Note: you can ask me a follow up question by @ mentioning me again :speech_balloon:
@tulip hazel Kapa.ai is still learning and improving, please let me know how I did by reacting below.
@dapper oracle is this fine, or will run infintelyt:
export const purgePresences = internalMutation({
handler: async (ctx) => {
const presences = await ctx.db.query("presences").take(10);
if (presences.length === 0) return;
await Promise.all(
presences.map((presence) => ctx.db.delete("presences", presence._id))
);
ctx.scheduler.runAfter(0, internal.presences.purgePresences);
},
});
Let me check the knowledge base for you again. One moment! :books:
There are two issues with this code:
-
It will run infinitely. The early return
if (presences.length === 0) return;is correct in theory, but only if the table actually empties out. If new presences are being inserted continuously, it will keep running forever. That may or may not be your intent. -
Incorrect
ctx.db.deletecall. In Convex,ctx.db.deletetakes only a document ID, not a table name + ID. It should be:
ctx.db.delete(presence._id)
not ctx.db.delete("presences", presence._id).
Here's a corrected version:
export const purgePresences = internalMutation({
handler: async (ctx) => {
const presences = await ctx.db.query("presences").take(10);
if (presences.length === 0) return; // stops when table is empty
await Promise.all(
presences.map((presence) => ctx.db.delete(presence._id))
);
await ctx.scheduler.runAfter(0, internal.presences.purgePresences);
},
});
Also note: you should await the ctx.scheduler.runAfter(...) call (as shown above) to ensure it's properly scheduled. [Scheduled Functions]