Mongoose: Investigate custom schema type issue

Created on 26 Feb 2018  路  6Comments  路  Source: Automattic/mongoose

Most helpful comment

I took a look at this again today and finally got it to work.
A couple of notes

  1. I couldn't abide by the square having different side lengths. It sent the OCD ( that I didn't even know I had ) into a downward spiral.
  2. if you're nesting classes, you have to create an instance of the nested class in the cast function of the parent.

my changes

'use strict'

var assert = require('assert')
var mongoose = require('mongoose')
var Schema = mongoose.Schema

mongoose.connect('mongodb://localhost:27017/example')
// mongoose.set('debug', true)

class Square {
  constructor (u) {
    this.sides = u.sides
  }

  calculateArea () {
    return this.sides ** 2
  }

  toBSON () {
    return {
      sides: this.sides
    }
  }
}

class SquareSchema extends mongoose.SchemaType {
  cast (v) {
    return new Square(v)
  }
}

mongoose.Schema.Types.Square = SquareSchema

class Polygon {
  constructor (u) {
    this.sideA = u.sideA
    this.sideB = u.sideB
    this.square = u.square
  }

  calculateArea () {
    var t = this.square.calculateArea()
    var k = this.sideA * this.sideB
    return [t, k]
  }

  toBSON () {
    return {
      sideA: this.sideA,
      sideB: this.sideB,
      square: this.square
    }
  }
}

class PolygonSchema extends mongoose.SchemaType {
  cast (v) {
    let x = {
      sideA: v.sideA,
      sideB: v.sideB,
      square: new Square(v.square)
    }
    return new Polygon(x)
  }
}

mongoose.Schema.Types.Polygon = PolygonSchema

const schema = new Schema({
  poly: Polygon
})

const Mod = mongoose.model('Learning', schema)

var sq = new Square({
  sides: 5
})

var instance = new Mod({
  poly: {
    sideA: 15,
    sideB: 16,
    square: sq
  }
})

async function run () {
  await Mod.remove({})
  let saved = await instance.save()
  console.log(saved)
  let found = await Mod.findOne({ _id: instance._id })
  console.log(found.poly.calculateArea())
}

run().catch(console.error)

output

6174: node ./index.js
{ _id: 5aca1cf91eb1256f9eb98a3d,
  poly: Polygon { sideA: 15, sideB: 16, square: Square { sides: 5 } },
  __v: 0 }
[ 25, 240 ]
^C
6174:

All 6 comments

I took a look at this again today and finally got it to work.
A couple of notes

  1. I couldn't abide by the square having different side lengths. It sent the OCD ( that I didn't even know I had ) into a downward spiral.
  2. if you're nesting classes, you have to create an instance of the nested class in the cast function of the parent.

my changes

'use strict'

var assert = require('assert')
var mongoose = require('mongoose')
var Schema = mongoose.Schema

mongoose.connect('mongodb://localhost:27017/example')
// mongoose.set('debug', true)

class Square {
  constructor (u) {
    this.sides = u.sides
  }

  calculateArea () {
    return this.sides ** 2
  }

  toBSON () {
    return {
      sides: this.sides
    }
  }
}

class SquareSchema extends mongoose.SchemaType {
  cast (v) {
    return new Square(v)
  }
}

mongoose.Schema.Types.Square = SquareSchema

class Polygon {
  constructor (u) {
    this.sideA = u.sideA
    this.sideB = u.sideB
    this.square = u.square
  }

  calculateArea () {
    var t = this.square.calculateArea()
    var k = this.sideA * this.sideB
    return [t, k]
  }

  toBSON () {
    return {
      sideA: this.sideA,
      sideB: this.sideB,
      square: this.square
    }
  }
}

class PolygonSchema extends mongoose.SchemaType {
  cast (v) {
    let x = {
      sideA: v.sideA,
      sideB: v.sideB,
      square: new Square(v.square)
    }
    return new Polygon(x)
  }
}

mongoose.Schema.Types.Polygon = PolygonSchema

const schema = new Schema({
  poly: Polygon
})

const Mod = mongoose.model('Learning', schema)

var sq = new Square({
  sides: 5
})

var instance = new Mod({
  poly: {
    sideA: 15,
    sideB: 16,
    square: sq
  }
})

async function run () {
  await Mod.remove({})
  let saved = await instance.save()
  console.log(saved)
  let found = await Mod.findOne({ _id: instance._id })
  console.log(found.poly.calculateArea())
}

run().catch(console.error)

output

6174: node ./index.js
{ _id: 5aca1cf91eb1256f9eb98a3d,
  poly: Polygon { sideA: 15, sideB: 16, square: Square { sides: 5 } },
  __v: 0 }
[ 25, 240 ]
^C
6174:

@vkarpov15 , what do you think about it ?

@lineus, But the problem is typecasting is not possible in all cases. Since in few of the cases the type may be unknown

You're right 馃憤 Sorry I didn't catch that in your comment on #4356. I'll give it some more thought.

@NikhilAshodariya, i also think so. @lineus fighting! 馃憤

@NikhilAshodariya sounds like you need discriminators. In general, you rarely need custom types in mongoose

Was this page helpful?
0 / 5 - 0 ratings

Related issues

xpepermint picture xpepermint  路  115Comments

ruimgoncalves picture ruimgoncalves  路  59Comments

floatingLomas picture floatingLomas  路  61Comments

ChrisZieba picture ChrisZieba  路  76Comments

nparsons08 picture nparsons08  路  40Comments