fix: toInclude bug with nested associations (#47)

This commit is contained in:
Junyi 2020-12-24 07:21:46 +08:00 committed by GitHub
parent 6c4a73f260
commit 57003c6c02
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 61 additions and 60 deletions

View File

@ -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'],

View File

@ -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);
} }

View File

@ -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;
}; };

View File

@ -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',