Categories
MongoDB

Using MongoDB with Mongoose — Subdocuments

Spread the love

To make MongoDB database manipulation easy, we can use the Mongoose NPM package to make working with MongoDB databases easier.

In this article, we’ll look at how to use Mongoose to manipulate our MongoDB database.

Parents of Subdocuments

We can get the parent document from a child document.

For example, we can write:

async function run() {
  const mongoose = require('mongoose');
  const connection = mongoose.createConnection('mongodb://localhost:27017/test');
  const childSchema = new mongoose.Schema({ name: 'string' });
  const parentSchema = new mongoose.Schema({
    children: [childSchema],
    child: childSchema
  });
  const Child = await connection.model('Child', childSchema);
  const Parent = await connection.model('Parent', parentSchema);
  const parent = new Parent({ child: { name: 'Matt' }, children: [{ name: 'Matt' }] })
  await parent.save();
  console.log(parent === parent.child.parent());
  console.log(parent === parent.children[0].parent());
}
run();

Then both console log statements are true because the parent method returns the parent object of the child and a subdocument in the children fields.

If we have a deeply nested subdocument, we can call the ownerDocument method to get the root document:

async function run() {
  const { createConnection, Schema } = require('mongoose');
  const connection = createConnection('mongodb://localhost:27017/test');
  const parentSchema = new Schema({
    level1: new Schema({
      level2: new Schema({
        test: String
      })
    })
  });
  const Parent = await connection.model('Parent', parentSchema);
  const doc = new Parent({ level1: { level2: { test: 'test' } } });
  await doc.save();
  console.log(doc === doc.level1.level2.ownerDocument());
}
run();

We call the ownerDocument method with on the level2 subdocument to get the root document.

Therefore, the console log should log true .

Alternative Declaration Syntax for Arrays

We can declare nested documents in more than one way.

One way is to put the array straight into the schema object:

async function run() {
  const { createConnection, Schema } = require('mongoose');
  const connection = createConnection('mongodb://localhost:27017/test');
  const parentSchema = new Schema({
    children: [{ name: 'string' }]
  });
  const Parent = await connection.model('Parent', parentSchema);
  const doc = new Parent({ children: { name: 'test' } });
  await doc.save();
}
run();

We can also create a schema with the Schema constructor:

async function run() {
  const { createConnection, Schema } = require('mongoose');
  const connection = createConnection('mongodb://localhost:27017/test');
  const parentSchema = new Schema({
    children: [new Schema({ name: 'string' })]
  });
  const Parent = await connection.model('Parent', parentSchema);
  const doc = new Parent({ children: { name: 'test' } });
  await doc.save();
}
run();

Alternative Declaration Syntax for Single Nested Subdocuments

There are also 2 ways to declare subdocuments schema.

One way is to write:

async function run() {
  const { createConnection, Schema } = require('mongoose');
  const connection = createConnection('mongodb://localhost:27017/test');
  const schema = new Schema({
    nested: {
      prop: String
    }
  });
  const Parent = await connection.model('Parent', schema);
}
run();

or:

async function run() {
  const { createConnection, Schema } = require('mongoose');
  const connection = createConnection('mongodb://localhost:27017/test');
  const schema = new Schema({
    nested: {
      type: new Schema({ prop: String }),
      required: true
    }
  });
  const Parent = await connection.model('Parent', schema);
}
run();

Both ways will set the nested subdocument with the data type string.

Conclusion

We can work with MongoDB subdocuments in different ways with Mongoose.

By John Au-Yeung

Web developer specializing in React, Vue, and front end development.

Leave a Reply

Your email address will not be published. Required fields are marked *