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.
Id
is a class. To check if two Id
s 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 Id
s 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);