fix: association find and count
This commit is contained in:
parent
629a4de173
commit
04e9393dea
@ -1,4 +1,4 @@
|
||||
import { Utils, Op } from 'sequelize';
|
||||
import { Utils, Op, Sequelize } from 'sequelize';
|
||||
import _ from 'lodash';
|
||||
import { Context, Next } from '.';
|
||||
import {
|
||||
@ -12,6 +12,136 @@ import {
|
||||
import { DEFAULT_PAGE, DEFAULT_PER_PAGE } from '@nocobase/resourcer';
|
||||
import { filterByFields } from '../utils';
|
||||
|
||||
async function hasManyGet(instances, options: any = {}) {
|
||||
const where = {};
|
||||
|
||||
let Model = this.target;
|
||||
let instance;
|
||||
let values;
|
||||
|
||||
if (!Array.isArray(instances)) {
|
||||
instance = instances;
|
||||
instances = undefined;
|
||||
}
|
||||
|
||||
options = { ...options };
|
||||
|
||||
if (this.scope) {
|
||||
Object.assign(where, this.scope);
|
||||
}
|
||||
|
||||
if (instances) {
|
||||
values = instances.map(_instance => _instance.get(this.sourceKey, { raw: true }));
|
||||
|
||||
if (options.limit && instances.length > 1) {
|
||||
options.groupedLimit = {
|
||||
limit: options.limit,
|
||||
on: this, // association
|
||||
values
|
||||
};
|
||||
|
||||
delete options.limit;
|
||||
} else {
|
||||
where[this.foreignKey] = {
|
||||
[Op.in]: values
|
||||
};
|
||||
delete options.groupedLimit;
|
||||
}
|
||||
} else {
|
||||
where[this.foreignKey] = instance.get(this.sourceKey, { raw: true });
|
||||
}
|
||||
|
||||
options.where = options.where ?
|
||||
{ [Op.and]: [where, options.where] } :
|
||||
where;
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(options, 'scope')) {
|
||||
if (!options.scope) {
|
||||
Model = Model.unscoped();
|
||||
} else {
|
||||
Model = Model.scope(options.scope);
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(options, 'schema')) {
|
||||
Model = Model.schema(options.schema, options.schemaDelimiter);
|
||||
}
|
||||
|
||||
const results = await Model.findAndCountAll(options);
|
||||
if (instance) return results;
|
||||
|
||||
const result = {};
|
||||
for (const _instance of instances) {
|
||||
result[_instance.get(this.sourceKey, { raw: true })] = [];
|
||||
}
|
||||
|
||||
for (const _instance of results) {
|
||||
result[_instance.get(this.foreignKey, { raw: true })].push(_instance);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
async function belongsToManyGet(instance, options) {
|
||||
options = Utils.cloneDeep(options) || {};
|
||||
|
||||
const through = this.through;
|
||||
let scopeWhere;
|
||||
let throughWhere;
|
||||
|
||||
if (this.scope) {
|
||||
scopeWhere = { ...this.scope };
|
||||
}
|
||||
|
||||
options.where = {
|
||||
[Op.and]: [
|
||||
scopeWhere,
|
||||
options.where
|
||||
]
|
||||
};
|
||||
|
||||
if (Object(through.model) === through.model) {
|
||||
throughWhere = {};
|
||||
throughWhere[this.foreignKey] = instance.get(this.sourceKey);
|
||||
|
||||
if (through.scope) {
|
||||
Object.assign(throughWhere, through.scope);
|
||||
}
|
||||
|
||||
//If a user pass a where on the options through options, make an "and" with the current throughWhere
|
||||
if (options.through && options.through.where) {
|
||||
throughWhere = {
|
||||
[Op.and]: [throughWhere, options.through.where]
|
||||
};
|
||||
}
|
||||
|
||||
options.include = options.include || [];
|
||||
options.include.push({
|
||||
association: this.oneFromTarget,
|
||||
attributes: options.joinTableAttributes,
|
||||
required: true,
|
||||
paranoid: _.get(options.through, 'paranoid', true),
|
||||
where: throughWhere
|
||||
});
|
||||
}
|
||||
|
||||
let model = this.target;
|
||||
if (Object.prototype.hasOwnProperty.call(options, 'scope')) {
|
||||
if (!options.scope) {
|
||||
model = model.unscoped();
|
||||
} else {
|
||||
model = model.scope(options.scope);
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.prototype.hasOwnProperty.call(options, 'schema')) {
|
||||
model = model.schema(options.schema, options.schemaDelimiter);
|
||||
}
|
||||
|
||||
return model.findAndCountAll(options);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 查询数据列表
|
||||
*
|
||||
@ -53,31 +183,24 @@ export async function list(ctx: Context, next: Next) {
|
||||
if (!(associated instanceof AssociatedModel)) {
|
||||
throw new Error(`${associatedName} associated model invalid`);
|
||||
}
|
||||
const getAccessor = resourceField.getAccessors().get;
|
||||
const countAccessor = resourceField.getAccessors().count;
|
||||
// const getAccessor = resourceField.getAccessors().get;
|
||||
// const countAccessor = resourceField.getAccessors().count;
|
||||
options.scope = options.scopes||[];
|
||||
const rows = await associated[getAccessor]({
|
||||
joinTableAttributes: [],
|
||||
...options,
|
||||
context: ctx,
|
||||
});
|
||||
const associatedOptions = _.omit(options, [
|
||||
'attributes',
|
||||
'limit',
|
||||
'offset',
|
||||
'order'
|
||||
]);
|
||||
if (associatedOptions.include) {
|
||||
associatedOptions.include = associatedOptions.include.map(includeOptions => {
|
||||
includeOptions.attributes = [];
|
||||
return includeOptions;
|
||||
const association = AssociatedModel.associations[resourceField.options.name];
|
||||
if (resourceField instanceof BELONGSTOMANY) {
|
||||
data = await belongsToManyGet.call(association, associated, {
|
||||
joinTableAttributes: [],
|
||||
...options,
|
||||
context: ctx,
|
||||
});
|
||||
}
|
||||
if (resourceField instanceof HASMANY) {
|
||||
data = await hasManyGet.call(association, associated, {
|
||||
joinTableAttributes: [],
|
||||
...options,
|
||||
context: ctx,
|
||||
});
|
||||
}
|
||||
const count = await associated[countAccessor]({ ...associatedOptions, context: ctx });
|
||||
data = {
|
||||
rows,
|
||||
count,
|
||||
};
|
||||
} else {
|
||||
Model = ctx.db.getModel(resourceName);
|
||||
options = Model.parseApiJson({
|
||||
|
Loading…
Reference in New Issue
Block a user