adding index by userId on every single table
would there be any issue adding a userId on every table and an index so when I users asks to delete their data I can just find all their data and clear it?
8 Replies
In a user-centric app this is quite likely.
The only other thing that you might do is have a tree of ownership: Users have projects, projects have tasks.
User is deleted => projects are deleted => tasks within projects are deleted.
You can think of an index as a very efficient binary tree structure (it's not exactly binary under the hood), that allows retrieving documents for given field values quickly. Its primary cost is that it has to be updated when you make a write to the indexed table. (none of this is Convex specific)

so I tried this on a test user and the mutation hit 417ms
isn't the max like 1s?
do you think I should use an action and split this up into multiple mutations?
a user in my system could have a lot of messages or comments, so I'm wondering if I need to rethink my approach
Yeah, this is the problem with "cascading deletes".
Convex Ents have an implementation that uses scheduled mutations for this reason:
https://labs.convex.dev/convex-ents/schema/deletes
We'll probably add it as a separate helper into convex-helpers as well, so that you don't have to adopt Ents to use it.
But in general yeah, you basically need actions/scheduling to write (in this case delete) a large number of documents.
Cascading Deletes - Convex Ents
Relations, default values, unique fields and more for Convex
A more detailed explanation in this stack post (I just published):
https://stack.convex.dev/ents#cascading-deletes-soft-deletion-and-scheduled-deletion
Convex Ents: Manage your document relationships
Convex Ents is a library providing: simpler ways to model and query related documents, ability to easily map and filter documents, enforcing unique fi...
hmm, I do want to try out ents, but I'm not sure I'm mentally ready to refactor everything to adopt it 😆
it seems very useful though
is there a way to accept any generic Id, for example I want to create a mutation which does batch deletions
export const batchDeleteRecord = internalMutation({
args: {ids: v.array(v.id('')}
})
Yeah,
v.string()
since IDs are strings
You can also accept a table name (as a string or union of literals)
then you can const id = ctx.db.normalizeId(tableName, id)
to validate the id manually, before passing it to db.delete()ty!