mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-23 02:41:50 +03:00
80 lines
2.2 KiB
JavaScript
80 lines
2.2 KiB
JavaScript
|
const _ = require('lodash');
|
||
|
const _debug = require('ghost-ignition').debug._base;
|
||
|
const debug = _debug('ghost-query');
|
||
|
|
||
|
/**
|
||
|
* Enchances knex query builder with a join to relation configured in
|
||
|
*
|
||
|
* @param {Bookshelf.Model} model instance of Bookshelf model
|
||
|
* @param {String[]} relationsToLoad relations to be included in joins
|
||
|
*/
|
||
|
function withEager(model, relationsToLoad) {
|
||
|
const tableName = _.result(model.constructor.prototype, 'tableName');
|
||
|
|
||
|
return function (qb) {
|
||
|
if (!model.relationsMeta) {
|
||
|
return qb;
|
||
|
}
|
||
|
|
||
|
for (const [key, config] of Object.entries(model.relationsMeta)) {
|
||
|
if (relationsToLoad.includes(key)) {
|
||
|
const innerQb = qb
|
||
|
.leftJoin(config.targetTableName, `${tableName}.id`, `${config.targetTableName}.${config.foreignKey}`);
|
||
|
|
||
|
debug(`QUERY has posts: ${innerQb.toSQL().sql}`);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return qb;
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function load(options) {
|
||
|
if (!options) {
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
if (this.eagerLoad) {
|
||
|
if (!options.columns && options.withRelated && _.intersection(this.eagerLoad, options.withRelated).length) {
|
||
|
this.query(withEager(this, this.eagerLoad));
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* ## Pagination
|
||
|
* Extends `bookshelf.Model` native `fetch` and `fetchAll` methods with
|
||
|
* a join to "eager loaded" relation. An exaple of such loading is when
|
||
|
* there is a need to order by fields in the related table.
|
||
|
*
|
||
|
*/
|
||
|
module.exports = function eagerLoadPlugin(Bookshelf) {
|
||
|
const modelPrototype = Bookshelf.Model.prototype;
|
||
|
|
||
|
Bookshelf.Model = Bookshelf.Model.extend({
|
||
|
initialize: function () {
|
||
|
return modelPrototype.initialize.apply(this, arguments);
|
||
|
},
|
||
|
|
||
|
fetch: function () {
|
||
|
load.apply(this, arguments);
|
||
|
|
||
|
if (_debug.enabled('ghost-query')) {
|
||
|
debug('QUERY', this.query().toQuery());
|
||
|
}
|
||
|
|
||
|
return modelPrototype.fetch.apply(this, arguments);
|
||
|
},
|
||
|
|
||
|
fetchAll: function () {
|
||
|
load.apply(this, arguments);
|
||
|
|
||
|
if (_debug.enabled('ghost-query')) {
|
||
|
debug('QUERY', this.query().toQuery());
|
||
|
}
|
||
|
|
||
|
return modelPrototype.fetchAll.apply(this, arguments);
|
||
|
}
|
||
|
});
|
||
|
};
|