chore(database): merge fields arguments by path (#2331)

* feat: merge fields array arg

* chore: test

* chore: test

* chore: test

* fix: test
This commit is contained in:
ChengLei Shao 2023-07-28 16:46:43 +08:00 committed by GitHub
parent fd6d5ac2a6
commit 493965f848
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 137 additions and 71 deletions

View File

@ -112,80 +112,114 @@ describe('option parser', () => {
]); ]);
}); });
test('option parser with fields option', async () => { describe('options parser with fields option', () => {
let options: any = { it('should handle field and association', () => {
fields: ['id', 'posts'], const options: any = {
}; fields: ['id', 'posts'],
// 转换为 attributes: ['id'], include: [{association: 'posts'}] };
let parser = new OptionsParser(options, {
collection: User, // 转换为 attributes: ['id'], include: [{association: 'posts'}]
const parser = new OptionsParser(options, {
collection: User,
});
const params = parser.toSequelizeParams();
console.log(params);
expect(params['attributes']).toContain('id');
expect(params['include'][0]['association']).toEqual('posts');
}); });
let params = parser.toSequelizeParams();
expect(params['attributes']).toContain('id'); it('should handle field with association', () => {
expect(params['include'][0]['association']).toEqual('posts'); const options = {
appends: ['posts'],
};
// only appends const parser = new OptionsParser(options, {
options = { collection: User,
appends: ['posts'], });
}; const params = parser.toSequelizeParams();
parser = new OptionsParser(options, { expect(params['attributes']['include']).toEqual([]);
collection: User, expect(params['include'][0]['association']).toEqual('posts');
}); });
params = parser.toSequelizeParams();
expect(params['attributes']['include']).toEqual([]);
expect(params['include'][0]['association']).toEqual('posts');
// fields with association field it('should handle field with association field', () => {
options = { // fields with association field
fields: ['id', 'posts.title'], const options = {
}; fields: ['id', 'posts.title'],
};
parser = new OptionsParser(options, { const parser = new OptionsParser(options, {
collection: User, collection: User,
});
const params = parser.toSequelizeParams();
expect(params['attributes']).toContain('id');
expect(params['include'][0]['association']).toEqual('posts');
expect(params['include'][0]['attributes']).toContain('title');
}); });
params = parser.toSequelizeParams();
expect(params['attributes']).toContain('id');
expect(params['include'][0]['association']).toEqual('posts');
expect(params['include'][0]['attributes']).toContain('title');
// fields with nested field it('should handle nested fields option', () => {
options = { const options = {
fields: ['id', 'posts', 'posts.comments.content'], fields: ['posts', 'posts.title'],
}; };
parser = new OptionsParser(options, { const parser = new OptionsParser(options, {
collection: User, collection: User,
});
const params = parser.toSequelizeParams();
const postAssociationParams = params['include'][0];
expect(postAssociationParams['attributes']).toEqual({ include: [] });
}); });
params = parser.toSequelizeParams();
expect(params['attributes']).toContain('id');
expect(params['include'][0]['association']).toEqual('posts');
expect(params['include'][0]['attributes']).toEqual({ include: [] });
expect(params['include'][0]['include'][0]['association']).toEqual('comments');
// fields with expect it('should handle fields with association & association field', () => {
options = { // fields with nested field
except: ['id'], const options = {
}; fields: ['id', 'posts', 'posts.comments.content'],
parser = new OptionsParser(options, { };
collection: User,
const parser = new OptionsParser(options, {
collection: User,
});
const params = parser.toSequelizeParams();
const postAssociationParams = params['include'][0];
expect(params['attributes']).toContain('id');
expect(postAssociationParams['association']).toEqual('posts');
expect(postAssociationParams['attributes']).toEqual({ include: [] });
expect(postAssociationParams['include'][0]['association']).toEqual('comments');
}); });
params = parser.toSequelizeParams();
expect(params['attributes']['exclude']).toContain('id');
// expect with association it('should handle except option', () => {
options = { // fields with expect
fields: ['posts'], const options = {
except: ['posts.id'], except: ['id'],
}; };
const parser = new OptionsParser(options, {
collection: User,
});
parser = new OptionsParser(options, { const params = parser.toSequelizeParams();
collection: User, expect(params['attributes']['exclude']).toContain('id');
}); });
params = parser.toSequelizeParams();
expect(params['include'][0]['attributes']['exclude']).toContain('id'); it('should handle fields with except option', () => {
// expect with association
const options = {
fields: ['posts'],
except: ['posts.id'],
};
const parser = new OptionsParser(options, {
collection: User,
});
const params = parser.toSequelizeParams();
expect(params['include'][0]['attributes']['exclude']).toContain('id');
});
}); });
test('option parser with multiple association', () => { test('option parser with multiple association', () => {

View File

@ -378,23 +378,33 @@ describe('repository find', () => {
}); });
}); });
it('should only output filed in fields args', async () => { describe('find with fields', () => {
const resp = await User.model.findOne({ it('should only output filed in fields args', async () => {
attributes: [], const users = await User.repository.find({
include: [ fields: ['profile.salary'],
{ });
association: 'profile',
attributes: ['salary'], const firstUser = users[0].toJSON();
}, expect(Object.keys(firstUser)).toEqual(['profile']);
], expect(Object.keys(firstUser.profile)).toEqual(['salary']);
}); });
const users = await User.repository.find({ it('should output all fields when field has relation field', async () => {
fields: ['profile', 'profile.salary', 'profile.id'], const users = await User.repository.find({
}); fields: ['profile.salary', 'profile'],
});
const firstUser = users[0].toJSON(); const firstUser = users[0].toJSON();
expect(Object.keys(firstUser)).toEqual(['profile']); expect(Object.keys(firstUser)).toEqual(['profile']);
expect(Object.keys(firstUser.profile)).toEqual([
'id',
'createdAt',
'updatedAt',
'salary',
'userId',
'description',
]);
});
}); });
it('append with associations', async () => { it('append with associations', async () => {

View File

@ -240,6 +240,9 @@ export class OptionsParser {
protected parseAppends(appends: Appends, filterParams: any) { protected parseAppends(appends: Appends, filterParams: any) {
if (!appends) return filterParams; if (!appends) return filterParams;
// sort appends by path length
appends = lodash.sortBy(appends, (append) => append.split('.').length);
/** /**
* set include params * set include params
* @param model * @param model
@ -287,6 +290,25 @@ export class OptionsParser {
// if include from filter, remove fromFilter attribute // if include from filter, remove fromFilter attribute
if (existIncludeIndex != -1) { if (existIncludeIndex != -1) {
delete queryParams['include'][existIncludeIndex]['fromFilter']; delete queryParams['include'][existIncludeIndex]['fromFilter'];
// set include attributes to all attributes
if (
Array.isArray(queryParams['include'][existIncludeIndex]['attributes']) &&
queryParams['include'][existIncludeIndex]['attributes'].length == 0
) {
queryParams['include'][existIncludeIndex]['attributes'] = {
include: [],
};
}
}
if (
lastLevel &&
existIncludeIndex != -1 &&
lodash.get(queryParams, ['include', existIncludeIndex, 'attributes', 'include'])?.length == 0
) {
// if append is last level and association exists, ignore it
return;
} }
// if association not exist, create it // if association not exist, create it