#gf

15 messages · Page 1 of 1 (latest)

dapper oracleBOT
#

Hi @tulip hazel. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:

#

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 n results of the query (or less if the query doesn't have n results)."

[.take() API]

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.

tulip hazel
#

@dapper oracle is there a way to just purge all documents in a table

dapper oracleBOT
#

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

[YOLO: Fast MVP]

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)));

[Writing Data]

⚠️ 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.

tulip hazel
#

@dapper oracle is it about for you to run a infiitely running scheduled mutation????

dapper oracleBOT
#

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.

tulip hazel
#

@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);
},
});

dapper oracleBOT
#

Let me check the knowledge base for you again. One moment! :books:

#

There are two issues with this code:

  1. 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.

  2. Incorrect ctx.db.delete call. In Convex, ctx.db.delete takes 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]

Summary: The logic is sound — it will stop once the table is empty. But if you want a true one-time purge, this pattern works correctly as long as no new documents are being inserted concurrently. If new documents keep coming in, it will indeed run indefinitely until they stop.

Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: