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 () => {
let options: any = {
fields: ['id', 'posts'],
};
// 转换为 attributes: ['id'], include: [{association: 'posts'}]
let parser = new OptionsParser(options, {
collection: User,
describe('options parser with fields option', () => {
it('should handle field and association', () => {
const options: any = {
fields: ['id', 'posts'],
};
// 转换为 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');
expect(params['include'][0]['association']).toEqual('posts');
it('should handle field with association', () => {
const options = {
appends: ['posts'],
};
// only appends
options = {
appends: ['posts'],
};
const parser = new OptionsParser(options, {
collection: User,
});
const params = parser.toSequelizeParams();
parser = new OptionsParser(options, {
collection: User,
expect(params['attributes']['include']).toEqual([]);
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
options = {
fields: ['id', 'posts.title'],
};
it('should handle field with association field', () => {
// fields with association field
const options = {
fields: ['id', 'posts.title'],
};
parser = new OptionsParser(options, {
collection: User,
const parser = new OptionsParser(options, {
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
options = {
fields: ['id', 'posts', 'posts.comments.content'],
};
it('should handle nested fields option', () => {
const options = {
fields: ['posts', 'posts.title'],
};
parser = new OptionsParser(options, {
collection: User,
const parser = new OptionsParser(options, {
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
options = {
except: ['id'],
};
parser = new OptionsParser(options, {
collection: User,
it('should handle fields with association & association field', () => {
// fields with nested field
const options = {
fields: ['id', 'posts', 'posts.comments.content'],
};
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
options = {
fields: ['posts'],
except: ['posts.id'],
};
it('should handle except option', () => {
// fields with expect
const options = {
except: ['id'],
};
const parser = new OptionsParser(options, {
collection: User,
});
parser = new OptionsParser(options, {
collection: User,
const params = parser.toSequelizeParams();
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', () => {

View File

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

View File

@ -240,6 +240,9 @@ export class OptionsParser {
protected parseAppends(appends: Appends, filterParams: any) {
if (!appends) return filterParams;
// sort appends by path length
appends = lodash.sortBy(appends, (append) => append.split('.').length);
/**
* set include params
* @param model
@ -287,6 +290,25 @@ export class OptionsParser {
// if include from filter, remove fromFilter attribute
if (existIncludeIndex != -1) {
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