Mongoose

Mongoose is an NPM package that allows a simple and schema'd Javascript entrypoint to your Mongo database.

Basics

Setup

Install mongoose: npm i mongoose and ensure your database is running.

Project

Create a new file called server.js and put this within.

// Initilize database

const mongoose = require("mongoose");
const dbName = "test";
mongoose.connect(`mongodb://localhost:27017/${dbName}`, {
  useNewUrlParser: true,
  useUnifiedTopology: true,
});

// Create test schema

const testSchema = new mongoose.Schema({
  name: String,
  age: Number,
  friends: [String],
});

// Create a model from your schema

// this first param is the name of your collection in your test database
const Test = mongoose.model("test", testSchema);

// Connect to database

const db = mongoose.connection;
db.on("error", console.error.bind(console, "connection error:"));
db.once("open", () => {
  console.log(`Mongoose DB "${dbName}" initialized\n`)
});

This will have created your basics. You can now start creating queries, inserting items into your database, etc.

Schemas and Models

Basic schemas are written very simply using a standard JSON format.

The following schema is for a registration form. It has five fields, all with differing implementations. Most basic, you can just put the key followed by it's type. If you want extended functionality, you can utilize it by using object notation.

const attendeeSchema = new mongoose.Schema({
  firstName: {
    type: String,
    required: true,
  },
  lastName: String,
  email: {
    type: String,
    required: true,
    match: /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/,
  },
  shirt: {
    type: String,
    enum: ['XS', 'S', 'M', 'L', 'XL', 'XXL'],
    required: true,
  },
  skillLevel: {
    type: String,
    enum: ['beginner', 'intermediate', 'expert'],
  }
});

Once your schema is created, you will then create a model that will be utilized within your code.

// mongoose.model(collection, schema), where collection is the
// name of the collection in your database.
const Attendee = mongoose.model('attendee', attendeeSchema);

This makes it easy to encapsulate the whole thing inside of a file for export in a node project.

const mongoose = require('mongoose');

const attendeeSchema = new mongoose.Schema({
  ...
});

const Attendee = mongoose.model('Attendee', attendeeSchema);

module.exports = Attendee;

Querying a Model[4-5]

Depending on how you want to handle the results, you can either return a promise or use a callback.

// Promise
const result = await Attendee.findOne({ name: 'John' }).exec();
const results = await Attendee.find({ name: 'John' }).exec();

// Callback
const result = Attendee.findOne({ name: 'John' }, (err, res) => { /* ... */ });
const results = Attendee.find({ name: 'John' }, (err, res) => { /* ... */ });

When the database gets queried by Mongoose, the return values are special objects that include helpful methods and other stuff. If you only want the JSON returned back, you can finish the query with a call to lean instead of exec.

// Promise
const result = await Attendee.findOne({ name: 'John' }).lean();
// Callback
const result = Attendee.findOne({ name: 'John' }).lean().exec((err, res) => {});

Populating a Model/Table Joins

In defining a schema, you can set a ref that will allow you to pull related data easily from another table.

const userSchema = new mongoose.Schema({
  username: String,
  password: String,
});

const postSchema = newmongoose.Schema({
  user: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User',
  },
  content: String,
});

const User = mongoose.model('User', userSchema);
const Post = mongoose.model('Post', postSchema);

When querying this, we have to use the populate command to grab the field we want to be populated/joined. The argument it takes is the name of the field we want populated.

const queriedPost = await Post.findOne().populate('user').exec();

/*
resulting object with "existing" data:

{
  user: {
    username: "Bob",
    password: "RobertIsCool",
  },
  content: "A cool post",
}

*/

Remote Database

mongoose.connect('mongodb://username:password@host:port', {useNewUrlParser: true});

Troubleshooting

Return Object

The return of a query is not a plain Javascript object and will show weird behavior when trying to add to/remove from/modify it. If you want a plain Javascript object in return, you can use .lean() within your chain to cast it.

References

  1. https://mongoosejs.com/
  2. https://stackoverflow.com/questions/33614229/how-to-use-mongo-mongoose-to-connect-to-a-remote-database
  3. https://mongoosejs.com/docs/connections.html
  4. https://mongoosejs.com/docs/api.html#model_Model-find
  5. https://stackoverflow.com/a/41148831/14857724

Last modified: 202208110451