How to write a Mongoose model in ES6 / ES2015

28,938

Solution 1

I'm not sure why you're attempting to use ES6 classes in this case. mongoose.Schema is a constructor to create new schemas. When you do

var Blacklist = mongoose.Schema({});

you are creating a new schema using that constructor. The constructor is designed so that behaves exactly like

var Blacklist = new mongoose.Schema({});

What you're alternative,

class Blacklist extends mongoose.Schema {

does is create a subclass of the schema class, but you never actually instantiate it anywhere

You'd need to do

export default mongoose.model('Blacklist', new Blacklist());

but I wouldn't really recommend it. There's nothing "more ES6y" about what you are doing. The previous code is perfectly reasonable and is the recommended API for Mongoose.

Solution 2

Mongoose can natively support es6 classes (since 4.7, and with no transpiler…).

Just write:

const mongoose = require('mongoose')
const { Model, Schema } = mongoose

const schema = new Schema({
  type: String,
  ip: String,
  details: String,
  reason: String,
})

class Tenant extends Model {}

module.exports = mongoose.model(Tenant, schema, 'tenant');

Solution 3

Why would you want to do it? mongoose.Schema is not expected to be used in this way. It doesn't use inheritance.

mongoose.Schema is a constructor that takes an object as the first parameter both in ES5 and ES6. No need for ES6 classes here.

Thus even with ES6 the proper way is to have:

const Blacklist = mongoose.Schema({
  type: String,
  ip: String,
  details: String,
  reason: String,
});

Solution 4

For those who find this searching around, the original question seems pretty valid to me. I'm using Babel transpiling ES6+ down to 5. My custom mongoose methods did not play well with my async/await code in my calling class. Notably this was null in my instance methods. Using the solution provided here, I was able to arrive at this solution that hopefully helps others searching around.

import mongoose from 'mongoose'

class Tenant extends mongoose.Schema {
  constructor() {
    const tenant = super({
      pg_id: Number,
      name: String,
      ...
    })

    tenant.methods.getAccountFields = this.getAccountFields
    tenant.methods.getCustomerTypes = this.getCustomerTypes
    tenant.methods.getContactFields = this.getContactFields
    ...
    tenant.methods.getModelFields = this.getModelFields

    return tenant
  }

  getAccountFields() {
    return this.getModelFields(this.account_fields_mapping)
  }

  getCustomerTypes() {
    //code
  }

  getContactFields() {
    //code
  }

  ...

  getModelFields(fields_mapping) {
    //code
  }
}

export default mongoose.model('Tenant', new Tenant)

Solution 5

To do things the ES6, class-like way, as the question states, I simply had to invoke the class with new in the exported mongoose.model function.

export default mongoose.model('Blacklist', new Blacklist)
Share:
28,938

Related videos on Youtube

Noah
Author by

Noah

Updated on August 13, 2020

Comments

  • Noah
    Noah almost 4 years

    I want to write my mongoose model in ES6. Basically replace module.exports and other ES5 things wherever possible. Here is what I have.

    import mongoose from 'mongoose'
    
    class Blacklist extends mongoose.Schema {
      constructor() {
        super({
          type: String,
          ip: String,
          details: String,
          reason: String
        })
      }
    }
    
    export default mongoose.model('Blacklist', Blacklist)
    

    I see this error in the console.

    if (!('pluralization' in schema.options)) schema.options.pluralization = this.options.pluralization;
                                     ^
    
    TypeError: Cannot use 'in' operator to search for 'pluralization' in undefined
    
  • HRK44
    HRK44 about 6 years
    This is not working, I have a MissingSchemaError thrown !