Skip to content

Commit 9096fe2

Browse files
authored
chore(aggregations): Use document_count from collection stats in the Aggregations input documents' total COMPASS-7799 (#5739)
* Use document_count from collection stats in the Aggregations input documents' total * rather always display the heading text * change other usage of count * remove unused stats, align initial value * remove unused import
1 parent 7790fb0 commit 9096fe2

File tree

11 files changed

+85
-65
lines changed

11 files changed

+85
-65
lines changed

packages/compass-aggregations/src/components/pipeline-builder-input-documents.tsx

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
toggleInputDocumentsCollapsed,
2121
} from '../modules/input-documents';
2222
import LoadingOverlay from './loading-overlay';
23+
import type { CollectionStats } from '../modules/collection-stats';
2324

2425
const headerStyles = css({
2526
display: 'flex',
@@ -67,7 +68,7 @@ type InputProps = {
6768
documents: DocumentType[];
6869
isExpanded: boolean;
6970
isLoading: boolean;
70-
count: number;
71+
count?: number;
7172
toggleInputDocumentsCollapsed: (arg0: boolean) => void;
7273
refreshInputDocuments: () => void;
7374
};
@@ -103,7 +104,7 @@ function PipelineBuilderInputDocuments({
103104
</IconButton>
104105
<Body className={headerTextStyles}>
105106
<b>
106-
{count} Document{count === 1 ? '' : 's'}
107+
{count ?? 'N/A'} Document{count === 1 ? '' : 's'}
107108
</b>{' '}
108109
in the collection
109110
</Body>
@@ -147,12 +148,18 @@ type InputDocuments = {
147148
};
148149

149150
export default connect(
150-
({ inputDocuments }: { inputDocuments: InputDocuments }) => {
151+
({
152+
inputDocuments,
153+
collectionStats,
154+
}: {
155+
inputDocuments: InputDocuments;
156+
collectionStats: CollectionStats;
157+
}) => {
151158
return {
152159
documents: inputDocuments.documents,
153160
isExpanded: inputDocuments.isExpanded,
154161
isLoading: inputDocuments.isLoading,
155-
count: inputDocuments.count,
162+
count: collectionStats?.document_count,
156163
};
157164
},
158165
{

packages/compass-aggregations/src/index.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ import type {
1515
OptionalDataServiceProps,
1616
RequiredDataServiceProps,
1717
} from './modules/data-service';
18-
import { mongoDBInstanceLocator } from '@mongodb-js/compass-app-stores/provider';
18+
import {
19+
collectionModelLocator,
20+
mongoDBInstanceLocator,
21+
} from '@mongodb-js/compass-app-stores/provider';
1922
import { workspacesServiceLocator } from '@mongodb-js/compass-workspaces/provider';
2023
import { preferencesLocator } from 'compass-preferences-model/provider';
2124
import { atlasAuthServiceLocator } from '@mongodb-js/atlas-service/provider';
@@ -41,6 +44,7 @@ export const CompassAggregationsHadronPlugin = registerHadronPlugin(
4144
atlasAiService: atlasAiServiceLocator,
4245
pipelineStorage: pipelineStorageLocator,
4346
connectionInfoAccess: connectionInfoAccessLocator,
47+
collection: collectionModelLocator,
4448
}
4549
);
4650

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import type { Reducer } from 'redux';
2+
import type Collection from 'mongodb-collection-model';
3+
4+
export type CollectionStats = {
5+
document_count?: number;
6+
};
7+
8+
export const INITIAL_STATE: CollectionStats = {
9+
document_count: undefined,
10+
};
11+
12+
export function pickCollectionStats(collection: Collection): CollectionStats {
13+
const { document_count } = collection.toJSON();
14+
return {
15+
document_count,
16+
};
17+
}
18+
19+
enum CollectionStatsActions {
20+
CollectionStatsFetched = 'compass-aggregations/collection-stats/CollectionStatsFetched',
21+
}
22+
23+
const reducer: Reducer<CollectionStats> = (state = INITIAL_STATE, action) => {
24+
if (action.type === CollectionStatsActions.CollectionStatsFetched) {
25+
return {
26+
...pickCollectionStats(action.collection),
27+
};
28+
}
29+
return state;
30+
};
31+
32+
export const collectionStatsFetched = (collection: Collection) => {
33+
return { type: CollectionStatsActions.CollectionStatsFetched, collection };
34+
};
35+
36+
export default reducer;

packages/compass-aggregations/src/modules/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import countDocuments from './count-documents';
2828
import isDataLake from './is-datalake';
2929
import workspace from './workspace';
3030
import aggregationWorkspaceId from './aggregation-workspace-id';
31+
import collectionStats from './collection-stats';
3132
import type { ThunkAction, ThunkDispatch } from 'redux-thunk';
3233
import type { PipelineBuilder } from './pipeline-builder/pipeline-builder';
3334
import type { PipelineStorage } from '@mongodb-js/my-queries-storage/provider';
@@ -85,6 +86,7 @@ const rootReducer = combineReducers({
8586
collectionsFields,
8687
insights,
8788
searchIndexes,
89+
collectionStats,
8890
});
8991

9092
export type RootState = ReturnType<typeof rootReducer>;

packages/compass-aggregations/src/modules/input-documents.spec.ts

Lines changed: 1 addition & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,37 +25,14 @@ describe('input documents module', function () {
2525

2626
describe('#updateInputDocuments', function () {
2727
it('returns the ActionTypes.DocumentsFetchFinished action', function () {
28-
expect(updateInputDocuments(10, [], null)).to.deep.equal({
28+
expect(updateInputDocuments([], null)).to.deep.equal({
2929
type: ActionTypes.DocumentsFetchFinished,
30-
count: 10,
3130
documents: [],
3231
error: null,
3332
});
3433
});
3534
});
3635

37-
describe('#refreshInputDocuments', function () {
38-
context('when the data service is connected', function () {
39-
context('when the count succeeds', function () {
40-
context('when the aggregation succeeds', function () {
41-
it('sets the count and documents in the state', function () {});
42-
});
43-
44-
context('when the aggregation fails', function () {
45-
it('sets the error in the state', function () {});
46-
});
47-
});
48-
49-
context('when the count fails', function () {
50-
it('sets the error in the state', function () {});
51-
});
52-
});
53-
54-
context('when the dataservice is not connected', function () {
55-
it('sets the error in the state', function () {});
56-
});
57-
});
58-
5936
describe('#reducer', function () {
6037
context(
6138
'when the action is not toggle input documents collapsed',
@@ -65,7 +42,6 @@ describe('input documents module', function () {
6542
documents: [],
6643
error: null,
6744
isExpanded: true,
68-
count: null,
6945
isLoading: false,
7046
});
7147
});
@@ -80,7 +56,6 @@ describe('input documents module', function () {
8056
documents: [],
8157
error: null,
8258
isExpanded: false,
83-
count: null,
8459
isLoading: false,
8560
});
8661
});

packages/compass-aggregations/src/modules/input-documents.ts

Lines changed: 7 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ type DocumentsFetchStartedAction = {
2020

2121
type DocumentsFetchFinishedAction = {
2222
type: ActionTypes.DocumentsFetchFinished;
23-
count: number | null;
2423
documents: HadronDocument[];
2524
error: Error | null;
2625
};
@@ -31,15 +30,13 @@ export type InputDocumentsAction =
3130
| DocumentsFetchStartedAction;
3231

3332
export type InputDocumentsState = {
34-
count: number | null;
3533
documents: HadronDocument[];
3634
error: Error | null;
3735
isExpanded: boolean;
3836
isLoading: boolean;
3937
};
4038

4139
export const INITIAL_STATE: InputDocumentsState = {
42-
count: null,
4340
documents: [],
4441
error: null,
4542
isExpanded: true,
@@ -71,7 +68,6 @@ const reducer = (
7168
) {
7269
return {
7370
...state,
74-
count: action.count,
7571
documents: action.documents,
7672
error: action.error,
7773
isLoading: false,
@@ -91,12 +87,10 @@ export const loadingInputDocuments = (): DocumentsFetchStartedAction => ({
9187
});
9288

9389
export const updateInputDocuments = (
94-
count: number | null,
9590
documents: HadronDocument[],
9691
error: Error | null
9792
): DocumentsFetchFinishedAction => ({
9893
type: ActionTypes.DocumentsFetchFinished,
99-
count,
10094
documents,
10195
error,
10296
});
@@ -122,38 +116,21 @@ export const refreshInputDocuments = (): PipelineBuilderThunkAction<
122116
| undefined,
123117
};
124118

125-
// maxTimeMS defaults to null here because the aggregation options field's
126-
// maxTimeMS defaults to empty and the preference defaults to undefined.
127-
// We need a timeout on count because for timeseries estimatedCount() seems
128-
// to just do a colscan and we need that timeout to be low compared to the
129-
// aggregation one anyway. For aggregations it is less critical because we
130-
// $limit to the first few records.
131-
const countOptions = { ...options, maxTimeMS: 500 };
132119
const aggregateOptions = { ...options };
133-
134120
const exampleDocumentsPipeline = [{ $limit: sampleSize }];
135121

136122
dispatch(loadingInputDocuments());
137123

138124
try {
139-
const data = await Promise.allSettled([
140-
dataService.estimatedCount(ns, countOptions),
141-
dataService.aggregate(ns, exampleDocumentsPipeline, aggregateOptions),
142-
]);
143-
144-
const count = data[0].status === 'fulfilled' ? data[0].value : null;
145-
const docs = data[1].status === 'fulfilled' ? data[1].value : [];
125+
const docs = await dataService.aggregate(
126+
ns,
127+
exampleDocumentsPipeline,
128+
aggregateOptions
129+
);
146130
const hadronDocs = docs.map((doc: any) => new HadronDocument(doc));
147-
148-
const error =
149-
data[0].status === 'rejected'
150-
? data[0].reason
151-
: data[1].status === 'rejected'
152-
? data[1].reason
153-
: null;
154-
dispatch(updateInputDocuments(count, hadronDocs, error));
131+
dispatch(updateInputDocuments(hadronDocs, null));
155132
} catch (error) {
156-
dispatch(updateInputDocuments(null, [], error as Error));
133+
dispatch(updateInputDocuments([], error as Error));
157134
}
158135
};
159136
};

packages/compass-aggregations/src/modules/pipeline-builder/stage-editor.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,15 +287,15 @@ export const loadStagePreview = (
287287
collationString,
288288
limit,
289289
largeLimit,
290-
inputDocuments,
290+
collectionStats,
291291
} = getState();
292292

293293
const options: PreviewOptions = {
294294
maxTimeMS: maxTimeMS ?? DEFAULT_MAX_TIME_MS,
295295
collation: collationString.value ?? undefined,
296296
sampleSize: largeLimit ?? DEFAULT_SAMPLE_SIZE,
297297
previewSize: limit ?? DEFAULT_PREVIEW_LIMIT,
298-
totalDocumentCount: inputDocuments.count ?? undefined,
298+
totalDocumentCount: collectionStats?.document_count,
299299
};
300300

301301
const previewDocs = await pipelineBuilder.getPreviewForStage(

packages/compass-aggregations/src/modules/pipeline-builder/text-editor-pipeline.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -219,7 +219,7 @@ export const loadPreviewForPipeline = (): PipelineBuilderThunkAction<
219219
collationString,
220220
limit,
221221
largeLimit,
222-
inputDocuments,
222+
collectionStats,
223223
dataService,
224224
pipelineBuilder: {
225225
textEditor: {
@@ -256,7 +256,7 @@ export const loadPreviewForPipeline = (): PipelineBuilderThunkAction<
256256
collation: collationString.value ?? undefined,
257257
sampleSize: largeLimit ?? DEFAULT_SAMPLE_SIZE,
258258
previewSize: limit ?? DEFAULT_PREVIEW_LIMIT,
259-
totalDocumentCount: inputDocuments.count ?? undefined,
259+
totalDocumentCount: collectionStats?.document_count,
260260
};
261261

262262
const previewDocs = await pipelineBuilder.getPreviewForPipeline(

packages/compass-aggregations/src/stores/store.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ describe('Aggregation Store', function () {
9999
isDataLake: INITIAL_STATE.isDataLake,
100100
pipelineBuilder: INITIAL_STATE.pipelineBuilder,
101101
focusMode: INITIAL_STATE.focusMode,
102+
collectionStats: INITIAL_STATE.collectionStats,
102103
collectionsFields: INITIAL_STATE.collectionsFields,
103104
searchIndexes: INITIAL_STATE.searchIndexes,
104105
});

packages/compass-aggregations/src/stores/store.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,11 @@ import type { AtlasAuthService } from '@mongodb-js/atlas-service/provider';
3737
import type { PipelineStorage } from '@mongodb-js/my-queries-storage/provider';
3838
import { maxTimeMSChanged } from '../modules/max-time-ms';
3939
import type { ConnectionInfoAccess } from '@mongodb-js/compass-connections/provider';
40+
import type { Collection } from '@mongodb-js/compass-app-stores/provider';
41+
import {
42+
pickCollectionStats,
43+
collectionStatsFetched,
44+
} from '../modules/collection-stats';
4045

4146
export type ConfigureStoreOptions = CollectionTabPluginMetadata &
4247
Partial<{
@@ -74,6 +79,7 @@ export type AggregationsPluginServices = {
7479
atlasAiService: AtlasAiService;
7580
pipelineStorage?: PipelineStorage;
7681
connectionInfoAccess: ConnectionInfoAccess;
82+
collection: Collection;
7783
};
7884

7985
export function activateAggregationsPlugin(
@@ -90,6 +96,7 @@ export function activateAggregationsPlugin(
9096
atlasAuthService,
9197
pipelineStorage,
9298
connectionInfoAccess,
99+
collection: collectionModel,
93100
}: AggregationsPluginServices,
94101
{ on, cleanup, addCleanup }: ActivateHelpers
95102
) {
@@ -161,6 +168,7 @@ export function activateAggregationsPlugin(
161168
// should be 'hidden'.
162169
localStorage.getItem(INITIAL_PANEL_OPEN_LOCAL_STORAGE_KEY) === 'true',
163170
},
171+
collectionStats: pickCollectionStats(collectionModel),
164172
},
165173
applyMiddleware(
166174
thunk.withExtraArgument({
@@ -201,6 +209,12 @@ export function activateAggregationsPlugin(
201209
}
202210
});
203211

212+
on(collectionModel, 'change:status', (model: Collection, status: string) => {
213+
if (status === 'ready') {
214+
store.dispatch(collectionStatsFetched(model));
215+
}
216+
});
217+
204218
// If stored pipeline was passed through options and we are not editing,
205219
// restore pipeline
206220
if (!editingView && options.aggregation) {

0 commit comments

Comments
 (0)