Search code examples
knex.jsbookshelf.js

Return the model data and its related data in a many-to-many association


I have the following tables:

tasklists: id (PK)
users: id (PK)
tasklist_resources: userId (FK to users.id), tasklistId (FK to tasklists.id)

And I'm defining the relation in their model like this:

let bookshelf = require('./base');

var User,
    Users;

User = bookshelf.Model.extend({
    tableName: 'users',
    taskLists: function() {
        return this.belongsToMany('TaskList', 'tasklist_resources', 'userId', 'tasklistId');
    }
});

Users = bookshelf.Collection.extend({
    model: User
});

module.exports = {
    User: bookshelf.model('User', User),
    Users: bookshelf.collection('Users', Users)
};

And this:

let bookshelf = require('./base');

var TaskListResource,
    TaskListResources;

TaskListResource = bookshelf.Model.extend({
    tableName: 'tasklist_resources',
    users: function() {
        return this.belongsToMany('User', 'tasklist_resources', 'tasklistId', 'userId');
    }
});

TaskListResources = bookshelf.Collection.extend({
    model: TaskListResource
});

module.exports = {
    TaskListResource: bookshelf.model('TaskListResource', TaskListResource),
    TaskListResources: bookshelf.collection('TaskListResources', TaskListResources)
};

Then I'm trying to return the complete user info if the row is found in the joining table:

new TaskListResource({
                tasklistId: req.params.tasklistId,
                userId: req.params.id
            })
            .fetch({
                withRelated: [ 'users' ]
            })
            .then(result => {
                res.status(200).json(result);
            })

But it's returning only the values from the tasklist_resources table (e.g. [{"tasklistId":1,"userId":1}] ). What am I missing?


Solution

  • Got it working by using the TaskList model to retrieve the resources (users) associated to a taskList.

    let bookshelf = require('./base');
    
    var TaskList,
        TaskLists;
    
    TaskList = bookshelf.Model.extend({
        tableName: 'tasklists',
        createdByUser: function () {
            return this.belongsTo('User', 'createdBy');
        },
        resources: function() {
            return this.belongsToMany('User', 'tasklist_resources', 'tasklistId', 'userId', 'id');
        }
    });
    
    TaskLists = bookshelf.Collection.extend({
        model: TaskList
    });
    
    module.exports = {
        TaskList: bookshelf.model('TaskList', TaskList),
        TaskLists: bookshelf.collection('TaskLists', TaskLists)
    };
    

    And to select the data:

    new TaskList({
                    id: req.params.tasklistId
                })
                .fetch({ withRelated: ['resources'] })
                .then(result => {
                    res.setHeader('X-InlineCount', result.related('resources').length);
                    res.setHeader('Access-Control-Expose-Headers', 'X-InlineCount');
    
                    res.json(result.related('resources'));
                })