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

rewrite left outer join for sub queries in bookshelf.js

注意:我没有共享数据库模式,因为我主要只是在寻求帮助 w.r.t。最后一步是 2 个子查询的 'left outer join'。

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 编写上述查询

let options = {columns: [  'Action.name', 'completed_At as completedAt', 
                       'deadline', 'notes', 
                       'ActionAssignedTo.action_Id as actionId',
           ]};

  let action2 = new Action(); 

  action2.query().innerJoin('Employee',  function () {
                            this.on('Action.created_By_Id', 'Employee.id')
                           .andOn('Employee.vendor_Id', bookshelf.knex.raw(1));
  });

  action2.query().innerJoin('ActionAssignedTo',  function () {
                            this.on('Action.id',  'ActionAssignedTo.action_Id')                    
                           .andOn('ActionAssignedTo.action_Id', bookshelf.knex.raw(5));
  });

  action2.query().where(function() {
        this.where('Action.created_By_Id', empId)
  });
  action2.query().groupBy('Action.id'); 
  action2.query().limit(2);
  action2.query().columns(options.columns);


  let action1; 

  action1 =  Action.where('id', actionId);
  action1.query().columns('id');

  return bookshelf.knex.raw('select * from ' 
                    + '(' + action1.query().toString() + ') AS act1'
                    + ' left Outer Join '
                    + '(' + action2.query().toString() + ') AS act2'
                    + ' on act1.id = act2.actionId');

我不喜欢使用 bookshelf.knex.raw 来使用左外连接,因为 knex.raw 和 bookshelf 给出的输出不同。

有什么方法可以直接使用书架图书馆'left Outer Join'。

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

我认为您的主要问题是您像使用 knex 一样使用 Bookshelf。 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 进行第一次查询以获取操作 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
    });

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

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