Mongoose document references with a one-to-many relationship Mongoose document references with a one-to-many relationship mongoose mongoose

Mongoose document references with a one-to-many relationship


Refer to population, here extract an example from Mongoose.

var mongoose = require('mongoose'), Schema = mongoose.Schemavar personSchema = Schema({  _id     : Schema.Types.ObjectId,  name    : String,  age     : Number,  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]});var storySchema = Schema({  _creator : { type: Schema.Types.ObjectId, ref: 'Person' },  title    : String,  fans     : [{ type: Schema.Types.ObjectId, ref: 'Person' }]});var Story  = mongoose.model('Story', storySchema);var Person = mongoose.model('Person', personSchema);

So the example about, Story model stores related Person._id in Story._creator. When you find a document of Story, you can use populate() method to define which attribute in Person model you want to retrieve at the same time, such as:

Story.findOne({_id: 'xxxxxxx'}).populate('person', 'name age').exec(function(err, story) {  console.log('Story title: ', story.title);  console.log('Story creator', story.person.name);});

I believe this is what you looking for. Or else, you can use nested collections instead.


The previous answers to this question were helpful, but it may be useful to see more detailed code. The below code is from my Express.js backend for my application. My application allows users to write reviews. When querying the user, I return all of the reviews that the user has made.

user_model.js

import mongoose, { Schema } from 'mongoose';const UserSchema = new Schema({  firstname: String,  lastname: String,  username: { type: String, unique: true },  reviews: [{ type: Schema.Types.ObjectId, ref: 'Review' }],}, {  toJSON: {    virtuals: true,  },});const UserModel = mongoose.model('User', UserSchema);export default UserModel;

review_model.js

import mongoose, { Schema } from 'mongoose';const ReviewSchema = new Schema({  body: String,  username: String,  rating: Number,}, {  toJSON: {    virtuals: true,  },});const ReviewModel = mongoose.model('Review', ReviewSchema);export default ReviewModel;

review_controller.js

// . . .export const createReview = (req, res) => {    const review = new Review();    review.username = req.body.username;    review.rating = req.body.rating;    review.body = req.body.body;    review.save()      .then((result) => {        User.findOne({ username: review.username }, (err, user) => {            if (user) {                // The below two lines will add the newly saved review's                 // ObjectID to the the User's reviews array field                user.reviews.push(review);                user.save();                res.json({ message: 'Review created!' });            }        });      })      .catch((error) => {        res.status(500).json({ error });      });};

user_controller.js

 export const createUser = (req, res) => {   const user = new User();   user.username = req.body.username;   user.email = req.body.email;   user.save()       .then((result) => {            res.json({ message: 'User created!', result });        })        .catch((error) => {          res.status(500).json({ error });        });    };// . . .// returns the user object associated with the username if any// with the reviews field containing an array of review objects // consisting of the reviews created by the userexport const getUser = (req, res) => {    User.findOne({ username: req.params.username })      .populate('reviews')      .then((result) => {        res.json(result);      })      .catch((error) => {        res.status(500).json({ error });      });  };


As in population docs said

var aaron = new Person({ _id: 0, name: 'Aaron', age: 100 });aaron.save(function (err) {  if (err) return handleError(err);  var story1 = new Story({    title: "Once upon a timex.",    _creator: aaron._id    // assign the _id from the person  });  story1.save(function (err) {    if (err) return handleError(err);    // thats it!  });  //then add story to person  aaron.stories.push(story1);  aaron.save(callback);});