Marventus
Marventus

Reputation: 874

How to extend schemas in Mongoose?

I'm trying to set up an imbricated Schema model in Mongoose in which a few Schemas could be used as basis for more complex ones that will all be sharing the same base properties, in order not to repeat these for every subsequent schema that requires them (DRY principles). The ultimate goal is to store all of these under the same MongoDB collection.

Here's a rough idea of what I tried to do, using lodash extend:

/* Schemas */

import { Schema } from "mongoose";
import * as _ from 'lodash';

var PersonSchema: Schema = new Schema({
    email:      {type: String, required:true, unique:true},
    lastName:   {type: String, required:true},
    firstName:  {type: String, required:true}
});

export var UserSchema: Schema = _.merge( {}, PersonSchema, {
    password:   {type: String, required:true},
    versionTC:  {type: String, required:true}
});


/* Models */

import mongoose = require("mongoose");
import { Document, Model } from "mongoose";

export interface UserModel extends Document {}
export interface UserModelStatic extends Model<UserModel> {}
export const User = mongoose.model<UserModel, UserModelStatic>("User", UserSchema, "users");

Then, I'm setting up a Users API with Node and Express using the following configuration for POST:

import { Response, Request, NextFunction, Router } from "express";
import { User, UserModel } from "../models/user";

// Create method
public create(req: Request, res: Response, next: NextFunction) {
    const user = new User(req.body);
    user.save().then(user => {
        res.json(user.toObject());
        next();
    }).catch(next);
}

// POST route, calling the create() method above
router.post("/users", (req: Request, res: Response, next: NextFunction) => {
    new UsersApi().create(req, res, next);
});

With that setup, every time I try to post to my API omitting either of the new UserSchema properties (versionTC or password), the user still gets saved into Mongo, despite the fact that they are both defined as required: true.

However, if I omit any of the properties from the PersonSchema (firstName, lastName or email), the POST fails as expected with a 500 error.

Lastly, if I define all 5 properties in my UserSchema without extending PersonSchema with lodash, any missed properties in the POST request body will result in a 500 server error (again, as expected).

I'm convinced that this is not an issue with Mongoose and that I'm most likely doing something wrong, but I just can't figure out what that is. Any help would be greatly appreciated.

Upvotes: 1

Views: 3160

Answers (1)

Marventus
Marventus

Reputation: 874

I ended up using the mongoose-extend-schema npm package:

import extendSchema = require('mongoose-extend-schema');

export var UserSchema: Schema = extendSchema(PersonSchema, {
    password:   {type: String, required:true},
    versionTC:  {type: String, required:true}
});

Upvotes: 0

Related Questions