Skip to content

Commit 068ab78

Browse files
authored
[DataGridPremium] Improve aggregation performance for multiple columns (mui#16097)
1 parent 3fe74a9 commit 068ab78

File tree

4 files changed

+75
-88
lines changed

4 files changed

+75
-88
lines changed

packages/x-data-grid-premium/src/hooks/features/aggregation/createAggregationLookup.ts

Lines changed: 51 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,20 @@ import {
1919
import { getAggregationRules } from './gridAggregationUtils';
2020
import { gridAggregationModelSelector } from './gridAggregationSelectors';
2121

22-
const getAggregationCellValue = ({
23-
apiRef,
24-
groupId,
25-
field,
26-
aggregationFunction,
27-
aggregationRowsScope,
28-
}: {
29-
apiRef: React.MutableRefObject<GridApiPremium>;
30-
groupId: GridRowId;
31-
field: string;
32-
aggregationFunction: GridAggregationFunction;
33-
aggregationRowsScope: DataGridPremiumProcessedProps['aggregationRowsScope'];
34-
}) => {
22+
const getGroupAggregatedValue = (
23+
groupId: GridRowId,
24+
apiRef: React.MutableRefObject<GridApiPremium>,
25+
aggregationRowsScope: DataGridPremiumProcessedProps['aggregationRowsScope'],
26+
aggregatedFields: string[],
27+
aggregationRules: GridAggregationRules,
28+
position: GridAggregationPosition,
29+
) => {
30+
const groupAggregationLookup: GridAggregationLookup[GridRowId] = {};
31+
const aggregatedValues: { aggregatedField: string; values: any[] }[] = [];
32+
33+
const rowIds = apiRef.current.getRowGroupChildren({ groupId });
3534
const filteredRowsLookup = gridFilteredRowsLookupSelector(apiRef);
36-
const rowIds: GridRowId[] = apiRef.current.getRowGroupChildren({ groupId });
3735

38-
const values: any[] = [];
3936
rowIds.forEach((rowId) => {
4037
if (aggregationRowsScope === 'filtered' && filteredRowsLookup[rowId] === false) {
4138
return;
@@ -53,51 +50,43 @@ const getAggregationCellValue = ({
5350
return;
5451
}
5552

56-
if (typeof aggregationFunction.getCellValue === 'function') {
57-
const row = apiRef.current.getRow(rowId);
58-
values.push(aggregationFunction.getCellValue({ row }));
59-
} else {
60-
values.push(apiRef.current.getCellValue(rowId, field));
61-
}
62-
});
53+
const row = apiRef.current.getRow(rowId);
6354

64-
return aggregationFunction.apply({
65-
values,
66-
groupId,
67-
field, // Added per user request in https://github.com/mui/mui-x/issues/6995#issuecomment-1327423455
68-
});
69-
};
55+
for (let j = 0; j < aggregatedFields.length; j += 1) {
56+
const aggregatedField = aggregatedFields[j];
57+
const columnAggregationRules = aggregationRules[aggregatedField];
7058

71-
const getGroupAggregatedValue = ({
72-
groupId,
73-
apiRef,
74-
aggregationRowsScope,
75-
aggregatedFields,
76-
aggregationRules,
77-
position,
78-
}: {
79-
groupId: GridRowId;
80-
apiRef: React.MutableRefObject<GridApiPremium>;
81-
aggregationRowsScope: DataGridPremiumProcessedProps['aggregationRowsScope'];
82-
aggregatedFields: string[];
83-
aggregationRules: GridAggregationRules;
84-
position: GridAggregationPosition;
85-
}) => {
86-
const groupAggregationLookup: GridAggregationLookup[GridRowId] = {};
59+
const aggregationFunction = columnAggregationRules.aggregationFunction;
60+
const field = aggregatedField;
8761

88-
for (let j = 0; j < aggregatedFields.length; j += 1) {
89-
const aggregatedField = aggregatedFields[j];
90-
const columnAggregationRules = aggregationRules[aggregatedField];
62+
if (aggregatedValues[j] === undefined) {
63+
aggregatedValues[j] = {
64+
aggregatedField,
65+
values: [],
66+
};
67+
}
68+
69+
if (typeof aggregationFunction.getCellValue === 'function') {
70+
aggregatedValues[j].values.push(aggregationFunction.getCellValue({ row }));
71+
} else {
72+
const colDef = apiRef.current.getColumn(field);
73+
aggregatedValues[j].values.push(apiRef.current.getRowValue(row, colDef));
74+
}
75+
}
76+
});
77+
78+
for (let i = 0; i < aggregatedValues.length; i += 1) {
79+
const { aggregatedField, values } = aggregatedValues[i];
80+
const aggregationFunction = aggregationRules[aggregatedField].aggregationFunction;
81+
const value = aggregationFunction.apply({
82+
values,
83+
groupId,
84+
field: aggregatedField, // Added per user request in https://github.com/mui/mui-x/issues/6995#issuecomment-1327423455
85+
});
9186

9287
groupAggregationLookup[aggregatedField] = {
9388
position,
94-
value: getAggregationCellValue({
95-
apiRef,
96-
groupId,
97-
field: aggregatedField,
98-
aggregationFunction: columnAggregationRules.aggregationFunction,
99-
aggregationRowsScope,
100-
}),
89+
value,
10190
};
10291
}
10392

@@ -115,11 +104,11 @@ export const createAggregationLookup = ({
115104
aggregationRowsScope: DataGridPremiumProcessedProps['aggregationRowsScope'];
116105
getAggregationPosition: DataGridPremiumProcessedProps['getAggregationPosition'];
117106
}): GridAggregationLookup => {
118-
const aggregationRules = getAggregationRules({
119-
columnsLookup: gridColumnLookupSelector(apiRef),
120-
aggregationModel: gridAggregationModelSelector(apiRef),
107+
const aggregationRules = getAggregationRules(
108+
gridColumnLookupSelector(apiRef),
109+
gridAggregationModelSelector(apiRef),
121110
aggregationFunctions,
122-
});
111+
);
123112

124113
const aggregatedFields = Object.keys(aggregationRules);
125114
if (aggregatedFields.length === 0) {
@@ -143,14 +132,14 @@ export const createAggregationLookup = ({
143132
if (hasAggregableChildren) {
144133
const position = getAggregationPosition(groupNode);
145134
if (position != null) {
146-
aggregationLookup[groupNode.id] = getGroupAggregatedValue({
147-
groupId: groupNode.id,
135+
aggregationLookup[groupNode.id] = getGroupAggregatedValue(
136+
groupNode.id,
148137
apiRef,
149-
aggregatedFields,
150138
aggregationRowsScope,
139+
aggregatedFields,
151140
aggregationRules,
152141
position,
153-
});
142+
);
154143
}
155144
}
156145
};

packages/x-data-grid-premium/src/hooks/features/aggregation/gridAggregationUtils.ts

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -86,18 +86,16 @@ export const mergeStateWithAggregationModel =
8686
aggregation: { ...state.aggregation, model: aggregationModel },
8787
});
8888

89-
export const getAggregationRules = ({
90-
columnsLookup,
91-
aggregationModel,
92-
aggregationFunctions,
93-
}: {
94-
columnsLookup: GridColumnRawLookup;
95-
aggregationModel: GridAggregationModel;
96-
aggregationFunctions: Record<string, GridAggregationFunction>;
97-
}) => {
89+
export const getAggregationRules = (
90+
columnsLookup: GridColumnRawLookup,
91+
aggregationModel: GridAggregationModel,
92+
aggregationFunctions: Record<string, GridAggregationFunction>,
93+
) => {
9894
const aggregationRules: GridAggregationRules = {};
9995

100-
Object.entries(aggregationModel).forEach(([field, columnItem]) => {
96+
// eslint-disable-next-line guard-for-in
97+
for (const field in aggregationModel) {
98+
const columnItem = aggregationModel[field];
10199
if (
102100
columnsLookup[field] &&
103101
canColumnHaveAggregationFunction({
@@ -111,7 +109,7 @@ export const getAggregationRules = ({
111109
aggregationFunction: aggregationFunctions[columnItem],
112110
};
113111
}
114-
});
112+
}
115113

116114
return aggregationRules;
117115
};

packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregation.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,11 @@ export const useGridAggregation = (
103103

104104
const aggregationRules = props.disableAggregation
105105
? {}
106-
: getAggregationRules({
107-
columnsLookup: gridColumnLookupSelector(apiRef),
108-
aggregationModel: gridAggregationModelSelector(apiRef),
109-
aggregationFunctions: props.aggregationFunctions,
110-
});
106+
: getAggregationRules(
107+
gridColumnLookupSelector(apiRef),
108+
gridAggregationModelSelector(apiRef),
109+
props.aggregationFunctions,
110+
);
111111

112112
// Re-apply the row hydration to add / remove the aggregation footers
113113
if (!areAggregationRulesEqual(rulesOnLastRowHydration, aggregationRules)) {

packages/x-data-grid-premium/src/hooks/features/aggregation/useGridAggregationPreProcessors.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ export const useGridAggregationPreProcessors = (
3636
(columnsState) => {
3737
const aggregationRules = props.disableAggregation
3838
? {}
39-
: getAggregationRules({
40-
columnsLookup: columnsState.lookup,
41-
aggregationModel: gridAggregationModelSelector(apiRef),
42-
aggregationFunctions: props.aggregationFunctions,
43-
});
39+
: getAggregationRules(
40+
columnsState.lookup,
41+
gridAggregationModelSelector(apiRef),
42+
props.aggregationFunctions,
43+
);
4444

4545
columnsState.orderedFields.forEach((field) => {
4646
const shouldHaveAggregationValue = !!aggregationRules[field];
@@ -76,11 +76,11 @@ export const useGridAggregationPreProcessors = (
7676
(value) => {
7777
const aggregationRules = props.disableAggregation
7878
? {}
79-
: getAggregationRules({
80-
columnsLookup: gridColumnLookupSelector(apiRef),
81-
aggregationModel: gridAggregationModelSelector(apiRef),
82-
aggregationFunctions: props.aggregationFunctions,
83-
});
79+
: getAggregationRules(
80+
gridColumnLookupSelector(apiRef),
81+
gridAggregationModelSelector(apiRef),
82+
props.aggregationFunctions,
83+
);
8484

8585
const hasAggregationRule = Object.keys(aggregationRules).length > 0;
8686

0 commit comments

Comments
 (0)