Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mongoose advanced custom schema object type

I couldn't find any example of an advanced custom schema type involving custom objects (or value-objects) in Mongoose >=4.4.

Imagine that I want to use a custom type like:

function Polygon(c) {
  this.bounds = [ /* some data */ ];
  this.npoints = /* ... */
  /* ... initialize polygon ... */
};

Polygon.prototype.area = function surfaceArea() { /**/ };

Polygon.prototype.toObject = function toObject() { return this.bounds; };

Next, I implement a custom SchemaType like:

function PolygonType(key, options) {
  mongoose.SchemaType.call(this, key, options, 'PolygonType');
}

PolygonType.prototype = Object.create(mongoose.SchemaType.prototype);

PolygonType.prototype.cast = function(val) {
  if (!val) return null;
  if (val instanceof Polygon) return val;
  return new Polygon(val)
}

PolygonType.prototype.default = function(val) {
  return new Polygon(val);
}

How can I assure that:

  1. Every time a new object is "hydrated" from db (mongoose init), I will have a Polygon instance and not a plain object. I understand it will use the cast function. assert(model.polygon instanceof Polygon)

  2. Every time I will save my Model the Polygon attribute should be encoded and stored as a plain object representation (Polygon.prototype.toObject()) that in this case is an Array object in mongodb.

  3. If I use model.toObject() it will recursively call the model.polygon.toObject() to have a full plain object representation of the document.
like image 707
Dario Avatar asked Jun 29 '16 08:06

Dario


People also ask

What is Mongoose schema type?

What is a SchemaType? You can think of a Mongoose schema as the configuration object for a Mongoose model. A SchemaType is then a configuration object for an individual property. A SchemaType says what type a given path should have, whether it has any getters/setters, and what values are valid for that path.

What is the type of Mongoose object ID?

In mongoose, the ObjectId type is used not to create a new uuid, rather it is mostly used to reference other documents. Here is an example: var mongoose = require('mongoose'); var Schema = mongoose. Schema, ObjectId = Schema.

Which schema types are not supported by Mongoose?

Mongoose does not natively support long and double datatypes for example, although MongoDB does. However, Mongoose can be extended using plugins to support these other types.


Video Answer


1 Answers

I found a solution thanks to @vkarpov15 on github.com:

  1. SchemaType.prototype.cast() is needed to correctly hydrate the document model from raw mongodb representation, and throw an error in case of invalid data.

  2. To customize mongodb persistence, I had to implement a toBSON() function in my custom type object prototype (i.e. Polygon).

  3. model.toObject() / model.toJSON() currently doesn't call recursively toObject()/toJSON() on all children, but it looks like it will be fixed. But I could overload it as temporary workaround assigning a custom schema.methods.toObject() instance method.

like image 111
Dario Avatar answered Oct 12 '22 13:10

Dario