Improve record group aggregate query performance (#15828)
This PR is a first step for improving the performance on boards and table with groups. It is related to : https://github.com/twentyhq/core-team-issues/issues/1870 Here we implement only a groupBy query for aggregate values in the group section. This also allows to improve the DX of aggregate computing and group by query creation and parsing. ## Demo Main : https://github.com/user-attachments/assets/5d2a8077-5322-4928-a551-f03583bcfb87 This PR : https://github.com/user-attachments/assets/d0e82b28-72c3-40f0-b5cb-045f1a736ffb ## Aggregate update bug fix This PR also solves a bug with aggregate update that was already present on main. The bug is linked to core views not being updated properly during a modification of the aggregate operation on a view. We should probably improve the view lifecycle and state management because it is a bit too complex right now. Main : https://github.com/user-attachments/assets/10dbfb8b-dfa0-4f21-8698-d222871a43e7 This PR : https://github.com/user-attachments/assets/bac41890-5191-4e4c-b82b-19b1039e9ab5 ## Miscellaneous - Fixed optimistic rendering of group by queries, when adding a new record, the aggregate recomputes well. ## TODO - We might want to improve the optimistic for group by queries that don't have records nor more than one dimension.
This commit is contained in:
+60
@@ -0,0 +1,60 @@
|
||||
import { upsertIntoArrayOfObjectsComparingId } from '@/utils/array/upsertIntoArrayOfObjectComparingId';
|
||||
|
||||
type TestObject = {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
|
||||
const mockTestObjects: TestObject[] = [
|
||||
{
|
||||
id: '1',
|
||||
name: 'Test 1',
|
||||
},
|
||||
{
|
||||
id: '2',
|
||||
name: 'Test 2',
|
||||
},
|
||||
{
|
||||
id: '3',
|
||||
name: 'Test 3',
|
||||
},
|
||||
{
|
||||
id: '4',
|
||||
name: 'Test 4',
|
||||
},
|
||||
];
|
||||
|
||||
describe('upsertIntoArrayOfObjectsComparingId', () => {
|
||||
it('should insert in empty array', () => {
|
||||
expect(
|
||||
upsertIntoArrayOfObjectsComparingId([], mockTestObjects[0]),
|
||||
).toStrictEqual([mockTestObjects[0]]);
|
||||
});
|
||||
|
||||
it('should insert in array', () => {
|
||||
const newItem: TestObject = {
|
||||
id: '5',
|
||||
name: 'Test 5',
|
||||
};
|
||||
|
||||
expect(
|
||||
upsertIntoArrayOfObjectsComparingId(mockTestObjects, newItem),
|
||||
).toStrictEqual([...mockTestObjects, newItem]);
|
||||
});
|
||||
|
||||
it('should replace in array', () => {
|
||||
const itemToReplace: TestObject = {
|
||||
id: '4',
|
||||
name: 'Test 4 replaced',
|
||||
};
|
||||
|
||||
expect(
|
||||
upsertIntoArrayOfObjectsComparingId(mockTestObjects, itemToReplace),
|
||||
).toStrictEqual([
|
||||
mockTestObjects[0],
|
||||
mockTestObjects[1],
|
||||
mockTestObjects[2],
|
||||
itemToReplace,
|
||||
]);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,22 @@
|
||||
import { findById } from '@/utils/array/findById';
|
||||
|
||||
export const upsertIntoArrayOfObjectsComparingId = <T extends { id: string }>(
|
||||
arrayToUpsertInto: T[],
|
||||
itemToUpsert: T,
|
||||
): T[] => {
|
||||
const alreadyExistingItemIndex = arrayToUpsertInto.findIndex(
|
||||
findById(itemToUpsert.id),
|
||||
);
|
||||
|
||||
const shouldReplaceItem = alreadyExistingItemIndex > -1;
|
||||
|
||||
if (shouldReplaceItem) {
|
||||
const newArray = [...arrayToUpsertInto];
|
||||
|
||||
newArray.splice(alreadyExistingItemIndex, 1, itemToUpsert);
|
||||
|
||||
return newArray;
|
||||
} else {
|
||||
return arrayToUpsertInto.concat(itemToUpsert);
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user