Skip to main content

Document IDs

Example: Relational Data Modeling

Every document in convex has a globally unique document ID that is automatically generated by the system.

const userId = await db.insert("users", { name: "Michael Jordan" });

You can access the ID of a document in the _id field:

const userId = user._id;

You can use this ID to always issue a very efficient point query within your functions using the get method:

const retrievedUser = await db.get(documentId);

Also, this same ID can be used to update that document in place:

await db.patch(documentId, { name: "Steph Curry" });

Convex generates an Id TypeScript type based on your schema that is parameterized over your table names:

import { Id } from "./_generated/dataModel";

const userId: Id<"users"> = user._id;

The Id class generated in convex/_generated/dataModel is an alias to the GenericId class in the convex/values entrypoint of the Convex npm package.

caution

Id is a class. To check if two Ids refer to the same document, use myId.equals(otherId).

Importantly, === won't work because two different instances of this class can refer to the same document.

References and relationships

In Convex, you can reference a document simply by embedding its Id in another document:

await db.insert("books", {
title,
ownerId: user._id,
});

You can follow references with db.get:

const user = await db.get(book.ownerId);

And query for documents with a reference:

const myBooks = await db
.query("books")
.filter(q => q.eq(q.field("ownerId"), user._id))
.collect();

Using Ids as references can allow you to build a complex data model.

Trading off deeply nested documents vs. relationships

While it's useful that Convex supports nested objects and arrays, should keep documents relatively small in size. In practice, we recommend limiting lists to no more than 5-10 elements and avoiding deeply nested documents.

Instead, leverage separate tables, documents, and references to structure your data. This will lead to better maintainability and performance as your project grows.

Serializing IDs

To turn an Id into a string, use the .toString method:

const idString = user._id.toString();

This can be inserted into the URL or stored outside of Convex.

You can recreate the Id class by passing the ID string into its constructor after the table name:

import { Id } from "./_generated/dataModel";

const userId = new Id("users", idString);