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:
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)
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.
model.toObject()
it will recursively call the model.polygon.toObject()
to have a full plain object representation of the document.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.
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.
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.
I found a solution thanks to @vkarpov15 on github.com:
SchemaType.prototype.cast()
is needed to correctly hydrate the document model from raw mongodb representation, and throw an error in case of invalid data.
To customize mongodb persistence, I had to implement a toBSON()
function in my custom type object prototype (i.e. Polygon
).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With