JKHeadley / rest-hapi

🚀 A RESTful API generator for Node.js
https://resthapi.com
MIT License
1.19k stars 153 forks source link

Nested associations using User and Group Models #94

Open jadgsam opened 6 years ago

jadgsam commented 6 years ago

Hi @JKHeadley, I would appreciate your advice to redefine the user and group model associations. My goal is to define Groups for "Companies", "Consumers" and "SysAdmin". It means I will have Companies with many Consumers and many Consumers belonging to many Companies. At the end, we are talking about having Users associated with a Group (Consumer or Company). However, it is not clear to me how should I make this nested association within the User model (having Users inside Users) or if I should split this into a different model.

Thanks in advance, @jadgsam

JKHeadley commented 6 years ago

Hi @jadgsam, I'm having some difficulty understanding your goal. It sounds like you need to make 4 models: Company, Consumer, SysAdmin, and User. You have defined that a Company can have many Consumers, so that will be a one_many/many_one association. If I understand you correctly, then it sounds like it would be best for you to treat Company, Consumer, and SysAdmin as a sort of "user profile" model. Basically, a user can belong to one or more profiles and a profile is assigned to one user (one_one association). Check out the samples below for a basic example:

user.model.js

'use strict';

module.exports = function (mongoose) {
    const modelName = "user";
    const Types = mongoose.Schema.Types;
    const Schema = new mongoose.Schema({
        company: {
            type: Types.ObjectId,
            ref: "company"
        },
        consumer: {
            type: Types.ObjectId,
            ref: "consumer"
        },
        sysAdmin: {
            type: Types.ObjectId,
            ref: "sysAdmin"
        },
    }, {collection: modelName});

    Schema.statics = {
        collectionName: modelName,
        associations: {
            company: {
                type: "ONE_ONE",
                model: "company"
            },
            consumer: {
                type: "ONE_ONE",
                model: "consumer"
            },
            sysAdmin: {
                type: "ONE_ONE",
                model: "sysAdmin"
            }
        }
    }
}

company.model.js

'use strict';

module.exports = function (mongoose) {
    const modelName = "company";
    const Types = mongoose.Schema.Types;
    const Schema = new mongoose.Schema({
        user: {
            type: Types.ObjectId,
            ref: "user"
        }
    }, {collection: modelName});

    Schema.statics = {
        collectionName: modelName,
        associations: {
            user: {
                type: "ONE_ONE",
                model: "user"
            },
            consumers: {
                type: "ONE_MANY",
                alias: "consumer",
                foreignField: "company",
                model: "consumer"
            }
        }
    }
}

consumer.model.js

'use strict';

module.exports = function (mongoose) {
    const modelName = "consumer";
    const Types = mongoose.Schema.Types;
    const Schema = new mongoose.Schema({
        user: {
            type: Types.ObjectId,
            ref: "user"
        },
        company: {
            type: Types.ObjectId,
            ref: "user"
        }
    }, {collection: modelName});

    Schema.statics = {
        collectionName: modelName,
        associations: {
            user: {
                type: "ONE_ONE",
                model: "user"
            },
            company: {
                type: "MANY_ONE",
                model: "company"
            },
        }
    }
}

sys-admin.model.js

'use strict';

module.exports = function (mongoose) {
    const modelName = "consumer";
    const Types = mongoose.Schema.Types;
    const Schema = new mongoose.Schema({
        user: {
            type: Types.ObjectId,
            ref: "user"
        },
    }, {collection: modelName});

    Schema.statics = {
        collectionName: modelName,
        associations: {
            user: {
                type: "ONE_ONE",
                model: "user"
            }
        }
    }
}
jadgsam commented 6 years ago

Thanks for your feedback, I was also doing some other tests by following a different approach but I will compare against yours.