Skip to content

Commit ce185fe

Browse files
authored
feat: Update covered queries with new links, esr order swap, copy change CLOUDP-323671 (#7012)
* update covered queries with new links, esr order swap, copy change * updated the spacing * fixing some dependencies * render the esr link conditionally * add test about esr * updated spacing and the brackets
1 parent d8469f2 commit ce185fe

File tree

6 files changed

+133
-40
lines changed

6 files changed

+133
-40
lines changed

packages/compass-indexes/src/components/create-index-fields.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ function CreateIndexFields({
9696
track('New Index Field Added', {
9797
context: 'Create Index Modal',
9898
});
99-
}, []);
99+
}, [onAddFieldClick]);
100100

101101
const comboboxOptions = schemaFields.map((value) => ({ value }));
102102

packages/compass-indexes/src/components/create-index-form/index-flow-section.spec.tsx

Lines changed: 62 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,55 @@ describe('IndexFlowSection', () => {
7575
});
7676
});
7777

78+
describe('when 4 index fields are filled in and user clicks on covered queries button', () => {
79+
const fields: Field[] = [
80+
{ name: 'field1', type: '1 (asc)' },
81+
{ name: 'field2', type: '-1 (desc)' },
82+
{ name: 'field3', type: '1 (asc)' },
83+
{ name: 'field4', type: '1 (asc)' },
84+
];
85+
86+
beforeEach(() => {
87+
renderComponent({ fields });
88+
screen.getByTestId('index-flow-section-covered-queries-button').click();
89+
});
90+
91+
it('renders the covered queries examples', () => {
92+
const coveredQueriesExamples = screen.getByTestId(
93+
'index-flow-section-covered-queries-examples'
94+
);
95+
expect(coveredQueriesExamples).to.exist;
96+
expect(coveredQueriesExamples).to.contain.text(
97+
JSON.stringify({
98+
field1: 1,
99+
field2: 2,
100+
field3: 3,
101+
field4: 4,
102+
})
103+
);
104+
});
105+
106+
it('renders the optimal query examples', () => {
107+
const optimalQueriesExamples = screen.getByTestId(
108+
'index-flow-section-optimal-queries-examples'
109+
);
110+
expect(optimalQueriesExamples).to.exist;
111+
expect(optimalQueriesExamples).to.contain.text(
112+
`{"field1":1,"field2":2,"field4":{"$gt":3}}.sort({"field3": 1})`
113+
);
114+
});
115+
116+
it('renders the Covered Queries Learn More link', () => {
117+
const link = screen.getByText('Learn about covered queries');
118+
expect(link).to.be.visible;
119+
});
120+
121+
it('renders the ESR Learn More link', () => {
122+
const link = screen.getByText('Learn about ESR');
123+
expect(link).to.be.visible;
124+
});
125+
});
126+
78127
describe('when 3 index fields are filled in and user clicks on covered queries button', () => {
79128
const fields: Field[] = [
80129
{ name: 'field1', type: '1 (asc)' },
@@ -107,12 +156,17 @@ describe('IndexFlowSection', () => {
107156
);
108157
expect(optimalQueriesExamples).to.exist;
109158
expect(optimalQueriesExamples).to.contain.text(
110-
`{"field1":1,"field2":{"$gt":2}}.sort(field3: 1})`
159+
`{"field1":1,"field3":{"$gt":2}}.sort({"field2": 1})`
111160
);
112161
});
113162

114-
it('renders the Learn More link', () => {
115-
const link = screen.getByText('Learn More');
163+
it('renders the Covered Queries Learn More link', () => {
164+
const link = screen.getByText('Learn about covered queries');
165+
expect(link).to.be.visible;
166+
});
167+
168+
it('renders the ESR Learn More link', () => {
169+
const link = screen.getByText('Learn about ESR');
116170
expect(link).to.be.visible;
117171
});
118172
});
@@ -141,7 +195,7 @@ describe('IndexFlowSection', () => {
141195
);
142196
expect(optimalQueriesExamples).to.exist;
143197
expect(optimalQueriesExamples).to.contain.text(
144-
`{"field1":1,"field2":{"$gt":2}}}`
198+
`{"field1":1,"field2":{"$gt":2}}`
145199
);
146200
expect(optimalQueriesExamples).to.contain.text(
147201
`{"field1":1}.sort({"field2":2})`
@@ -167,5 +221,9 @@ describe('IndexFlowSection', () => {
167221
screen.queryByTestId('index-flow-section-optimal-queries-examples')
168222
).not.to.exist;
169223
});
224+
225+
it('does not render ESR Learn More link', () => {
226+
expect(screen.queryByText('Learn about ESR')).not.to.exist;
227+
});
170228
});
171229
});

packages/compass-indexes/src/components/create-index-form/index-flow-section.tsx

Lines changed: 60 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,14 @@ const coveredQueriesHeaderStyles = css({
9292
marginRight: spacing[200],
9393
});
9494

95+
const coveredQueriesLinkStyles = css({
96+
marginTop: spacing[200],
97+
});
98+
99+
const optimalQueriesStyles = css({
100+
marginTop: spacing[400],
101+
});
102+
95103
export type IndexFlowSectionProps = {
96104
fields: Field[];
97105
createIndexFieldsComponent: JSX.Element | null;
@@ -148,31 +156,35 @@ const generateOptimalQueries = (
148156

149157
return (
150158
<>
151-
{`{"${firstFieldKey}":1,"${lastFieldKey}":{"$gt":2}}}`}
159+
{`{"${firstFieldKey}":1,"${lastFieldKey}":{"$gt":2}}`}
152160
<br />
153161
{`{"${firstFieldKey}":1}.sort({"${lastFieldKey}":2})`}
154162
</>
155163
);
156164
}
157165

158166
// If there are more than two fields, we want to show a longer optimal query with gt and sort
159-
// i.e. {a:1, b:2, c:{gt:3}}.sort({d:1})
167+
// i.e. {a:1, b:2, d:{gt:3}}.sort({c:1})
168+
169+
const secondToLastField = coveredQueriesArr[numOfFields - 2];
170+
const secondToLastFieldKey = Object.keys(secondToLastField)[0];
171+
160172
const optimalQueries = coveredQueriesArr
161-
.slice(0, -1)
162-
.reduce<Record<string, unknown>>((acc, obj, index) => {
173+
.slice(0, -2)
174+
.reduce<Record<string, unknown>>((acc, obj) => {
163175
const key = Object.keys(obj)[0];
164176
const value = obj[key];
165177

166-
if (index === numOfFields - 2) {
167-
acc[key] = { $gt: value };
168-
} else {
169-
acc[key] = value;
170-
}
178+
acc[key] = value;
171179

172180
return acc;
173181
}, {});
174182

175-
return JSON.stringify(optimalQueries) + `.sort(${lastFieldKey}: 1})`;
183+
// Put last field in range and second to last field in sort
184+
optimalQueries[lastFieldKey] = { $gt: coveredQueriesArr.length - 1 };
185+
return (
186+
JSON.stringify(optimalQueries) + `.sort({"${secondToLastFieldKey}": 1})`
187+
);
176188
};
177189

178190
const IndexFlowSection = ({
@@ -354,28 +366,15 @@ const IndexFlowSection = ({
354366
)}
355367
>
356368
{/* Covered Queries */}
357-
<Body
358-
className={codeStyles}
359-
data-testid="index-flow-section-covered-queries-examples"
360-
>
361-
{coveredQueries}
362-
</Body>
363369

364-
{!!optimalQueries && (
365-
<>
366-
<p>
367-
<span className={underlineStyles}>
368-
Follow the Equality, Sort, Range (ESR) Rule. This index is
369-
optimal for queries that have this pattern:
370-
</span>
371-
{/* Optimal queries */}
372-
<Body
373-
className={codeStyles}
374-
data-testid="index-flow-section-optimal-queries-examples"
375-
>
376-
{optimalQueries}
377-
</Body>
378-
</p>
370+
<div>
371+
<Body
372+
className={codeStyles}
373+
data-testid="index-flow-section-covered-queries-examples"
374+
>
375+
{coveredQueries}
376+
</Body>
377+
<div className={coveredQueriesLinkStyles}>
379378
<Link
380379
href="https://www.mongodb.com/docs/manual/core/query-optimization/"
381380
onClick={() => {
@@ -384,9 +383,37 @@ const IndexFlowSection = ({
384383
});
385384
}}
386385
>
387-
Learn More
386+
Learn about covered queries
388387
</Link>
389-
</>
388+
</div>
389+
</div>
390+
391+
{!!optimalQueries && (
392+
<div className={optimalQueriesStyles}>
393+
<span className={underlineStyles}>
394+
Follow the Equality, Sort, Range (ESR) Rule. This index is
395+
great for queries that have this pattern:
396+
</span>
397+
{/* Optimal queries */}
398+
<Body
399+
className={codeStyles}
400+
data-testid="index-flow-section-optimal-queries-examples"
401+
>
402+
{optimalQueries}
403+
</Body>
404+
<div className={coveredQueriesLinkStyles}>
405+
<Link
406+
href="https://www.mongodb.com/docs/manual/tutorial/equality-sort-range-guideline/"
407+
onClick={() => {
408+
track('ESR Learn More Clicked', {
409+
context: 'Create Index Modal',
410+
});
411+
}}
412+
>
413+
Learn about ESR
414+
</Link>
415+
</div>
416+
</div>
390417
)}
391418
</div>
392419
</>

packages/compass-indexes/src/components/create-index-form/query-flow-section.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ const QueryFlowSection = ({
160160
});
161161

162162
setHasNewChanges(false);
163-
}, [inputQuery, dbName, collectionName, onSuggestedIndexButtonClick]);
163+
}, [inputQuery, dbName, collectionName, onSuggestedIndexButtonClick, track]);
164164

165165
const handleQueryInputChange = useCallback((text: string) => {
166166
setInputQuery(text);

packages/compass-indexes/src/components/create-index-modal/create-index-modal.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ function CreateIndexModal({
6767
});
6868
}
6969
},
70-
[onCancelCreateIndexClick]
70+
[onCancelCreateIndexClick, track]
7171
);
7272

7373
useTrackOnChange(

packages/compass-telemetry/src/telemetry-events.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2849,6 +2849,13 @@ type CreateIndexCoveredQueriesLearnMoreClicked = CommonEvent<{
28492849
};
28502850
}>;
28512851

2852+
type CreateIndexESRLearnMoreClicked = CommonEvent<{
2853+
name: 'ESR Learn More Clicked';
2854+
payload: {
2855+
context: CreateIndexModalContext;
2856+
};
2857+
}>;
2858+
28522859
type CreateIndexInputIndexCopied = CommonEvent<{
28532860
name: 'Input Index Copied';
28542861
payload: {
@@ -3003,6 +3010,7 @@ export type TelemetryEvent =
30033010
| CreateIndexCodeEquivalentToggled
30043011
| CreateIndexCoveredQueriesButtonClicked
30053012
| CreateIndexCoveredQueriesLearnMoreClicked
3013+
| CreateIndexESRLearnMoreClicked
30063014
| CreateIndexIndexTabClicked
30073015
| CreateIndexModalCancelled
30083016
| CreateIndexModalClosed

0 commit comments

Comments
 (0)