Knows Not Much
Knows Not Much

Reputation: 31546

mongoose filter based on related table

I have developed a simple schema with 2 Tables Roles and Users. The users table references the role table.

I want to select all users which have a specific role.

Towards this I have written this code

models.js

var RoleSchema = new mongoose.Schema({
    rolename : {type: String, required: true}
});
var RoleModel = db.model('Role', RoleSchema, 'Role');

var UserSchema = new mongoose.Schema({
    username : {type: String, required: true},
    email : {type: String, required: true},
    role : {type: mongoose.Schema.Types.ObjectId, ref: 'Role', required: true}
});
var UserModel = db.model('User', UserSchema, 'User');
module.exports = {Role: RoleModel, User: UserModel};

app.js

var models = require('../models.js);

var rolename = req.params.rolename;
logger.info('came inside getUserByRole ' + rolename);
models.User 
.where('role.rolename').equals(rolename)    
.exec(function(err, users){
    if (err) res.json(501, 'Internal Error');
    if (users == null) res.json(404, 'No users found');
    res.json(200, users);
});

But this code returns all the users. my hope was that the user list will be filtered by the role name which I have specified.

I also tried

exports.getUsersByRole = function(req, res) {   
    var rolename = req.params.rolename;
    logger.info('came inside getUserByRole ' + rolename);
    models.User 
    .find({})
    .populate({
        path: 'role',
        match: {'role.rolename': rolename}
    })
    .exec(function(err, users){
        if (err) res.json(501, 'Internal Error');
        if (users == null) res.json(404, 'No users found');
        res.json(200, users);
    });
};

But this also returns all the users (and the role null). does not filter on rolename and does not populate the rolename.

Upvotes: 2

Views: 3348

Answers (1)

dylants
dylants

Reputation: 23340

Because the role is a reference, you'll need to populate as you've done in the second try. But this populate won't occur until the query is complete, so you'll need to filter after the initial query (similar to this answer).

So in your scenario, something like this:

models.User.find().populate("role").exec(function(err, users) {
    users = users.filter(function(user) {
        return user.role.rolename === req.params.rolename;
    });

    res.send(users);
});

Upvotes: 3

Related Questions