BugForge
All lessons
Databases · 06/09 5 min1 hands-on

Relations and populate

Store an id, not a copy. Then let populate fill in the related document when you read.

A post has an author. Don't copy the author's name into every post (it goes stale when they rename). Store a reference: the author's _id.

const postSchema = new mongoose.Schema({
  title: String,
  author: { type: mongoose.Schema.Types.ObjectId, ref: "User" },   // ref names the model
});

Reading it back

const post = await Post.findOne();
post.author;              // ObjectId("66f…"): just the id

const full = await Post.findOne().populate("author");
full.author.name;         // "Ada": the whole user document

populate runs a second lookup for you and swaps the id for the document.

Filtering by a reference

Post.find({ author: userId });   // all posts by this user

Comparing ids

post.author is an ObjectId object, not a string. post.author === req.user.id is always false. Use post.author.equals(id) or compare strings: String(post.author) === String(id).

Embed or reference?

  • Embed small things that belong to one parent and are read together (an order's line items).
  • Reference things that are shared or grow without limit (users, comments on a popular post).
Your turn · 1 exercise0/1 solved

Posts and their authors

Posts reference users. postsWithAuthors() returns every post with its author filled in (sorted by title), and postsBy(userId) returns one user's posts.

Loading editor…
Next in Databases
Pagination that adds up