Closed YannisMarios closed 6 years ago
Hi Yannis!
Both statements are correct. You still need a schema as you've demonstrated, e.g.
const schema = new Schema({ firstName: String, lastName: String });
Once you have that, you can use an ES6 class to define and add custom methods on your models. It's written in the next sentence after the one you've quoted:
Mongoose allows creating schemas from ES6 classes. The loadClass() function lets you pull in methods, statics, and virtuals from an ES6 class.
The functionality is limited to only defining these methods, statics and virtuals. (if I'm mistaken, someone can correct me).
A full example:
Using pure schema notation
const schema = new Schema({ firstName: String, lastName: String });
schema.methods.setName = function setName(firstName, lastName) => {
this.firstName = firstName;
this.lastName = lastName;
}
schema.statics.findByFirstName = function findByFirstName(firstName, cb) => {
return this.where('firstName', new RegExp(firstName, 'i')).exec(cb);
}
Using a mixed notation
const schema = new Schema({ firstName: String, lastName: String });
class User {
set name(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
static findByFirstName(firstName, cb) {
return this.where('firstName', new RegExp(firstName, 'i').exec(cb);
}
}
schema.loadClass(User);
As you can see, both examples define the initial schema. Afterwards the additional logic can be defined using both ways. Using the ES6 class notation makes you code easier to read and maintain, especially if you're adding a lot of methods, statics and virtuals. It can greatly reduce the amount of code you need to write, though this really depends on your own project.
ES6 classes do not provide an alternative to writing your schema. ES6 classes provide an alternative to writing additional methods for your Model.
Hopefully this has answered your question.
Hi @samcoenen,
Thanks for the reply. What I really want to do is to avoid code duplication because a lot of my mongoose schemas have common properties/fields. Since mongoose does not support schema inheritance ( I know about discriminators. I just don't want to store many of my docs in the same collection) I thought I might be able to use es6 classes for this. I seems I can't do that either.
Someone on slack proposed this solution but it is using flowtype: https://twitter.com/nodkz/status/902431500389539841
Thanks anyway.
@YannisMarios you should be able to implement schema inheritance using something like this:
function ChildSchema(obj) {
return baseSchema.clone().add(obj);
}
@vkarpov15
Ok I will try this.
Thanks
Hey Guys, But what if you extend the schema class (schema inheritance) like this:
class PersonSchema extends mongoose.Schema {
} to be honest I didn't try it.
@osfalos that should work fine. You'll most likely want to use Schema#add()
in the constructor but no reason why you can't use extends mongoose.Schema
3 years passed - nothing has changed. This is still unintuitive and extremely misleading. The docs could've stated it directly like "you can load methods and such, but not schema fields", but the devs decided to leave it as "lol you'll find out anyway when you will try and fail".
For those who'll stumble upon this issue while searching in Google just like me: seems like decorators + SchemaFactory.createForClass()
from NestJS do the job of keeping the things in one place without duplicating stuff. At least this way it makes sense.
Hi,
My versions: node: v10.5.0, mongoose: v5.2.7, mongodb: v4.0.0
I want to ask about creating schemas from ES6 classes. Here http://mongoosejs.com/docs/advanced_schemas.html#creating-from-es6-classes-using-loadclass it says: "Mongoose allows creating schemas from ES6 classes." which is not true since one still has to define schema fields separately like:
define the class:
and then:
I mean what is the point doing all this since I still have to define all schema fields separately?
Thank you