fix: toInclude bug with nested associations (#47)
This commit is contained in:
parent
6c4a73f260
commit
57003c6c02
@ -144,8 +144,7 @@ describe('toInclude', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it.skip('nested association', () => {
|
it('nested association', () => {
|
||||||
// TODO,输出 bars 的所有字段
|
|
||||||
toIncludeExpect({
|
toIncludeExpect({
|
||||||
fields: ['col1', 'bars', 'bars.baz'],
|
fields: ['col1', 'bars', 'bars.baz'],
|
||||||
}, true).toEqual({
|
}, true).toEqual({
|
||||||
@ -164,6 +163,25 @@ describe('toInclude', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('nested association', () => {
|
||||||
|
toIncludeExpect({
|
||||||
|
fields: ['col1', 'bars.baz', 'bars'],
|
||||||
|
}, true).toEqual({
|
||||||
|
attributes: [ 'col1' ],
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
association: 'bars',
|
||||||
|
include: [
|
||||||
|
{
|
||||||
|
association: 'baz',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
distinct: true,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('nested association', () => {
|
it('nested association', () => {
|
||||||
toIncludeExpect({
|
toIncludeExpect({
|
||||||
fields: ['col1', 'bars.col1', 'bars.col2', 'bars.baz'],
|
fields: ['col1', 'bars.col1', 'bars.col2', 'bars.baz'],
|
||||||
|
@ -265,7 +265,6 @@ export class FORMULA extends VIRTUAL {
|
|||||||
const fields = sourceTable.getFields();
|
const fields = sourceTable.getFields();
|
||||||
const data: any = {};
|
const data: any = {};
|
||||||
for (const [name, field] of fields) {
|
for (const [name, field] of fields) {
|
||||||
console.log(field.getType());
|
|
||||||
if (['formula', 'virtual'].indexOf((field.getType() as string).toLowerCase()) === -1) {
|
if (['formula', 'virtual'].indexOf((field.getType() as string).toLowerCase()) === -1) {
|
||||||
data[name] = this.getDataValue(name);
|
data[name] = this.getDataValue(name);
|
||||||
}
|
}
|
||||||
|
@ -99,15 +99,13 @@ export function toOrder(sort: string | string[], model: any): string[][] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function toInclude(options: any, context: ToIncludeContext = {}) {
|
export function toInclude(options: any, context: ToIncludeContext = {}) {
|
||||||
function makeFields(key) {
|
function makeFields(key: string) {
|
||||||
if (!Array.isArray(items[key])) {
|
if (!Array.isArray(items[key])) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
items[key].forEach(field => {
|
items[key].forEach(field => {
|
||||||
// 按点分隔转化为数组
|
// 按点分隔转化为数组
|
||||||
const arr: Array<string> = Array.isArray(field) ? Utils.cloneDeep(field) : field.split('.');
|
const [col, ...arr]: string[] = Array.isArray(field) ? Utils.cloneDeep(field) : field.split('.');
|
||||||
// 当前列
|
|
||||||
const col = arr.shift();
|
|
||||||
// 内嵌的情况
|
// 内嵌的情况
|
||||||
if (arr.length > 0) {
|
if (arr.length > 0) {
|
||||||
if (!children.has(col)) {
|
if (!children.has(col)) {
|
||||||
@ -122,26 +120,33 @@ export function toInclude(options: any, context: ToIncludeContext = {}) {
|
|||||||
children.get(col).fields[key].push(arr);
|
children.get(col).fields[key].push(arr);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 关系字段
|
if (key !== 'except') {
|
||||||
if (associations[col]) {
|
// 关系字段
|
||||||
const includeItem: any = {
|
if (associations[col]) {
|
||||||
association: col,
|
const includeItem: any = {
|
||||||
};
|
association: col,
|
||||||
if (includeWhere[col]) {
|
};
|
||||||
includeItem.where = includeWhere[col];
|
if (includeWhere[col]) {
|
||||||
|
includeItem.where = includeWhere[col];
|
||||||
|
}
|
||||||
|
include.set(col, includeItem);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 计数字段
|
||||||
|
const matches: Array<any> = col.match(/(.+)_count$/);
|
||||||
|
if (matches && associations[matches[1]]) {
|
||||||
|
attributes[key].push(model.withCountAttribute({
|
||||||
|
association: matches[1],
|
||||||
|
sourceAlias: sourceAlias
|
||||||
|
}));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
include.set(col, includeItem);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const matches: Array<any> = /(.+)_count$/.exec(col);
|
|
||||||
if (matches && associations[matches[1]]) {
|
|
||||||
attributes[key].push(model.withCountAttribute({
|
|
||||||
association: matches[1],
|
|
||||||
sourceAlias: sourceAlias
|
|
||||||
}));
|
|
||||||
} else {
|
} else {
|
||||||
attributes[key].push(col);
|
if (!attributes.except) {
|
||||||
|
attributes.except = [];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
attributes[key].push(col);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,31 +183,7 @@ export function toInclude(options: any, context: ToIncludeContext = {}) {
|
|||||||
|
|
||||||
makeFields('only');
|
makeFields('only');
|
||||||
makeFields('appends');
|
makeFields('appends');
|
||||||
|
makeFields('except');
|
||||||
if (Array.isArray(items.except) && items.except.length > 0) {
|
|
||||||
items.except.forEach(field => {
|
|
||||||
const arr: Array<string> = Array.isArray(field) ? Utils.cloneDeep(field) : field.split('.');
|
|
||||||
const col = arr.shift();
|
|
||||||
// 内嵌的情况
|
|
||||||
if (arr.length > 0) {
|
|
||||||
if (!children.has(col)) {
|
|
||||||
children.set(col, {
|
|
||||||
where: includeWhere[col],
|
|
||||||
fields: {
|
|
||||||
only: [],
|
|
||||||
except: [arr],
|
|
||||||
appends: [],
|
|
||||||
},
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
children.get(col).fields.except.push(arr);
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// 黑名单里只有字段
|
|
||||||
attributes.except.push(col);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const whereKey in includeWhere) {
|
for (const whereKey in includeWhere) {
|
||||||
if (children.has(whereKey)) {
|
if (children.has(whereKey)) {
|
||||||
@ -238,13 +219,18 @@ export function toInclude(options: any, context: ToIncludeContext = {}) {
|
|||||||
if (result.scopes) {
|
if (result.scopes) {
|
||||||
item.model = associations[key].target.scope(result.scopes);
|
item.model = associations[key].target.scope(result.scopes);
|
||||||
}
|
}
|
||||||
|
// 解决同时有关联和关联的子级关联时,关联的 attribute 被设置为空数组的问题
|
||||||
|
// ['user.profile.age', 'user.status', 'user', 'title', 'status']
|
||||||
|
if (include.has(key) && Array.isArray(item.attributes) && !item.attributes.length) {
|
||||||
|
delete item.attributes;
|
||||||
|
}
|
||||||
include.set(key, item);
|
include.set(key, item);
|
||||||
}
|
}
|
||||||
|
|
||||||
const data: any = {};
|
const data: any = {};
|
||||||
|
|
||||||
// 存在黑名单时
|
// 存在黑名单时
|
||||||
if (attributes.except.length > 0) {
|
if (attributes.except.length) {
|
||||||
data.attributes = {
|
data.attributes = {
|
||||||
exclude: attributes.except,
|
exclude: attributes.except,
|
||||||
};
|
};
|
||||||
@ -253,19 +239,17 @@ export function toInclude(options: any, context: ToIncludeContext = {}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 存在白名单时
|
// 存在白名单时
|
||||||
else if (attributes.only.length > 0) {
|
else if (attributes.only.length) {
|
||||||
data.attributes = [...attributes.only, ...attributes.appends];
|
data.attributes = [...attributes.only, ...attributes.appends];
|
||||||
}
|
}
|
||||||
// 只有附加字段时
|
// 只有附加字段时
|
||||||
else if (attributes.appends.length > 0) {
|
else if (attributes.appends.length) {
|
||||||
data.attributes = {
|
data.attributes = {
|
||||||
include: attributes.appends,
|
include: attributes.appends,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (include.size > 0) {
|
if (include.size) {
|
||||||
// TODO(bug): 当遇到多层关联时,attributes 控制不正确
|
|
||||||
// ['user.profile.age', 'user.status', 'user', 'title', 'status']
|
|
||||||
if (!data.attributes) {
|
if (!data.attributes) {
|
||||||
data.attributes = [];
|
data.attributes = [];
|
||||||
}
|
}
|
||||||
@ -273,17 +257,17 @@ export function toInclude(options: any, context: ToIncludeContext = {}) {
|
|||||||
data.distinct = true;
|
data.distinct = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Reflect.ownKeys(where).length > 0) {
|
if (Reflect.ownKeys(where).length) {
|
||||||
data.where = where;
|
data.where = where;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scopes.length > 0) {
|
if (scopes.length) {
|
||||||
data.scopes = scopes;
|
data.scopes = scopes;
|
||||||
}
|
}
|
||||||
|
|
||||||
const order = toOrder(options.sort, model);
|
const order = toOrder(options.sort, model);
|
||||||
|
|
||||||
if (order.length > 0) {
|
if (order.length) {
|
||||||
data.order = order;
|
data.order = order;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,4 +296,4 @@ export function isNumber(num) {
|
|||||||
return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);
|
return Number.isFinite ? Number.isFinite(+num) : isFinite(+num);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -51,7 +51,7 @@ describe('models.field', () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
it.only('sub table field', async () => {
|
it.skip('sub table field', async () => {
|
||||||
const [Collection, Field] = app.database.getModels(['collections', 'fields']);
|
const [Collection, Field] = app.database.getModels(['collections', 'fields']);
|
||||||
const options = {
|
const options = {
|
||||||
title: 'tests',
|
title: 'tests',
|
||||||
|
Loading…
Reference in New Issue
Block a user