-
Notifications
You must be signed in to change notification settings - Fork 75
Open
Description
Here is an example to enhance $include for [email protected]
export class MyService extends SequelizeService {
/**
* abstract function for defind associations
* @param {*} model current model
* @param {*} models all models inside the database
* @see {@link https://sequelize.org/docs/v6/core-concepts/assocs/ Associations}
* @example
* $include = {
* ["alias"]: {
* $required: true,
* $select: ["field_a", "field_b"],
* $sort: { "lastupdate": -1 },
* project_id: project_id,
* lastupdate: { $gte: startDate, $lte: endDate },
* $include: {
* ["alias"]: { ...nested },
* }
* },
* }
* @example $include = ["alias"]
*/
defindAssociations(model, models) {
// model.hasMany(models['other_table'], { as: "items", foreignKey: "item_id", targetKey: "id" });
}
setup(app, path) {
this.defindAssociations(this.Model, this.Model.sequelize.models);
const service = app.service(path);
service.publish((data, context) => app.channel(path)); // publish all events
// no pagination service "/all"
app.use(path + '/all', {
main: this,
async find(params) {
const data = await this.main.find({ query: params.query, paginate: false });
return { total: data.length, data };
}
});
}
filterQuery(params) {
if (params.query.$include) {
params.include = params.query.$include; // define for this.paramsToAdapter
// remove $include for parent call
params.query = { ...params.query };
delete params.query.$include;
}
return super.filterQuery(params);
}
paramsToAdapter(id, params, associations = this.Model.associations) {
const include = params.include;
let q = super.paramsToAdapter(id, params);
if (include) {
q.raw = false; // format result
q.include = this.parseInclude(associations, include);
for (let item of q.include) {
if (item.order) {
for (let o of item.order) {
q.order.push([item.as, ...o]);
}
delete item.order;
}
}
}
return q;
}
parseInclude(associations, $include) {
const include = [];
if (Array.isArray($include)) {
for (const tableAlias of $include) {
if (!associations[tableAlias])
throw new BadRequest(`Unknown relation "${tableAlias}" in $include`);
const { target, as } = associations[tableAlias];
const iOpt = {
model: target,
required: false,
as: as,
};
include.push(iOpt);
}
} else {
for (const tableAlias in $include) {
if (!associations[tableAlias])
throw new BadRequest(`Unknown relation "${tableAlias}" in $include`);
const { target, as } = associations[tableAlias];
let { $required, $include: child$include, ...query } = $include[tableAlias];
let id = this.options.id;
this.options.id = target.primaryKeyAttribute; // fool super.paramsToAdapter() use target primary key, as it auto appends the id to attributes
const q = this.paramsToAdapter(null, { query, paginate: false, include: child$include }, target.associations);
this.options.id = id; // undo change id
const iOpt = {
model: target,
required: !!$required,
as: as,
attributes: q.attributes,
where: q.where,
include: q.include,
order: q.order,
};
include.push(iOpt);
}
}
return include;
}
}
DaddyWarbucks
Metadata
Metadata
Assignees
Labels
No labels