在bookshelf.js中为子查询重写左外连接

时间:2018-02-12 10:56:12

标签: mysql knex.js bookshelf.js

注意:我没有共享数据库架构,因为我主要只是寻求帮助w.r.t.最后一步是2个子查询的“左外连接”。

jQuery('.play-btn').click(function () {
    alert();

    video = '<iframe width="400" height="300" src="' + jQuery(this).attr('data-video') + '" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>';

    jQuery(this).replaceWith(video);
});

我需要使用Bookshelf

编写上面的查询
select      *
from

(select     id
 from       Action
 where      id = 3) AS act1

left Outer Join

(select     Action.name, 
            completed_At as completedAt, 
            deadline, notes,
            ActionAssignedTo.action_Id as actionId, 
from        Action 
inner join  Employee 
on          Action.created_By_Id = Employee.id 
and         Employee.vendor_Id = 2
inner join  ActionAssignedTo
on          Action.id = ActionAssignedTo.action_Id 
and         ActionAssignedTo.action_Id = 3  
where       Action.created_By_Id = 7
group by    Action.id 
limit       2) AS act2

on          act1.id = act2.actionId

我并不热衷于使用bookshelf.knex.raw来使用左外连接作为knex.raw和bookshelf给出的输出不同。

有没有办法可以直接使用书架库进行'左外连接'。

我查看了代码,但似乎leftOuterJoin只将表名作为第一个参数,我需要的是一个查询。

1 个答案:

答案 0 :(得分:2)

我认为您的主要问题是您正在使用Bookshelf,就像您将使用knex一样。 Bookshelf旨在与您定义的模型一起使用,然后对它们进行查询。

以下是您应该拥有的模型

的示例
// Adding registry to avoid circular references
// Adding camelcase to get your columns names converted to camelCase
bookshelf.plugin(['bookshelf-camelcase', 'registry']);

// Reference: https://github.com/brianc/node-pg-types
// These two lines convert all bigint values coming from Postgres from JS string to JS integer.
// Removing these lines will mess up with Bookshelf count() methods and bigserial values
pg.types.setTypeParser(20, 'text', parseInt);

const Action = db.bookshelf.Model.extend({
    tableName: 'Action',

    createdBy: function createdBy() {
        return this.belongsTo(Employee, 'id', 'created_By_Id');
    },
    assignedTo: function assignedTo() {
        return this.hasMany(ActionAssignedTo, 'action_id');
    },
});

const Employee = db.bookshelf.Model.extend({
    tableName: 'Employee',

    createdActions: function createdActions() {
        return this.hasMany(Action, 'created_By_Id');
    },
});

const ActionAssignedTo = db.bookshelf.Model.extend({
    tableName: 'ActionAssignedTo',

    action: function action() {
        return this.belongsTo(Action, 'id', 'action_Id');
    },
    employee: function employee() {
        return this.belongsTo(Employee, 'id', 'employee_Id');
    },
});

module.exports = {
    Action: db.bookshelf.model('Action', Action),
    Employee: db.bookshelf.model('Employee', Employee),
    ActionAssignedTo: db.bookshelf.model('ActionAssignedTo', ActionAssignedTo),
    db,
};

然后,您就可以使用类似

的查询来获取结果
const Model = require('model.js');

Model.Action
    .where({ id: 3 })
    .fetchAll({ withRelated: ['createdBy', 'assignedTo', 'assignedTo.employee'] })
    .then(data => {
        // Do what you have to do
    });

只有Bookshelf中的一个查询,您无法实现的目标。您可能需要使用knex进行第一次查询以获取Action ID列表,然后将它们提供给Bookshelf.js

db.bookshelf.knex.raw(`
    select      ActionAssignedTo.action_Id as actionId,
    from        Action 
    inner join  Employee 
    on          Action.created_By_Id = Employee.id 
    and         Employee.vendor_Id = ?
    inner join  ActionAssignedTo
    on          Action.id = ActionAssignedTo.action_Id 
    and         ActionAssignedTo.action_Id = ?
    where       Action.created_By_Id = ?
    group by    Action.id 
    limit       ?`,
    [2, 3, 7, 2]
)
.then(result => {
    const rows = result.rows;
    // Do what you have to do
})

然后使用恢复的ID来获取这样的Bookshelf查询

Model.Action
    .query(qb => {
        qb.whereIn('id', rows);
    })
    .fetchAll({
        withRelated: [{
            'createdBy': qb => {
                qb.columns(['id', 'firstname', 'lastname']);
            },
            'assignedTo': qb => {
                qb.columns(['action_Id', 'employee_Id']);
            },
            'assignedTo.employee': qb => {
                qb.columns(['id', 'firstname', 'lastname']);
            },
        }],
        columns: ['id', 'name', 'completed_At', 'deadline', 'notes']
    })
    .fetchAll(data => {
        // Do what you have to do
    });

请注意,用于连接的列必须位于每个表的列列表中。如果省略列,则将选择所有列。

默认情况下,Bookshelf将检索所有列和所有根对象。默认值为LEFT OUTER JOIN