Skip to content

Commit dfa1e83

Browse files
[Discover][Context] Set trackTotalHits to false in requests to Elasticsearch (#108661) (#109679)
Co-authored-by: Matthias Wilhelm <[email protected]>
1 parent c31154b commit dfa1e83

File tree

7 files changed

+183
-46
lines changed

7 files changed

+183
-46
lines changed

src/plugins/discover/public/application/angular/context/api/__snapshots__/context.test.ts.snap

Lines changed: 65 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/plugins/discover/public/application/angular/context/api/anchor.test.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88

99
import { EsQuerySortValue, SortDirection } from '../../../../../../data/public';
1010
import { createIndexPatternsStub, createSearchSourceStub } from './_stubs';
11-
import { fetchAnchorProvider } from './anchor';
11+
import { fetchAnchorProvider, updateSearchSource } from './anchor';
1212
import { EsHitRecord, EsHitRecordList } from './context';
13+
import { indexPatternMock } from '../../../../__mocks__/index_pattern';
14+
import { savedSearchMock } from '../../../../__mocks__/saved_search';
1315

1416
describe('context app', function () {
1517
let fetchAnchor: (
@@ -114,6 +116,32 @@ describe('context app', function () {
114116
});
115117
});
116118

119+
it('should update search source correctly when useNewFieldsApi set to false', function () {
120+
const searchSource = updateSearchSource(
121+
savedSearchMock.searchSource,
122+
'id',
123+
[],
124+
false,
125+
indexPatternMock
126+
);
127+
const searchRequestBody = searchSource.getSearchRequestBody();
128+
expect(searchRequestBody._source).toBeInstanceOf(Object);
129+
expect(searchRequestBody.track_total_hits).toBe(false);
130+
});
131+
132+
it('should update search source correctly when useNewFieldsApi set to true', function () {
133+
const searchSource = updateSearchSource(
134+
savedSearchMock.searchSource,
135+
'id',
136+
[],
137+
true,
138+
indexPatternMock
139+
);
140+
const searchRequestBody = searchSource.getSearchRequestBody();
141+
expect(searchRequestBody._source).toBe(false);
142+
expect(searchRequestBody.track_total_hits).toBe(false);
143+
});
144+
117145
it('should reject with an error when no hits were found', function () {
118146
searchSourceStub._stubHits = [];
119147

src/plugins/discover/public/application/angular/context/api/anchor.ts

Lines changed: 39 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import {
1313
ISearchSource,
1414
IndexPatternsContract,
1515
EsQuerySortValue,
16+
IndexPattern,
1617
} from '../../../../../../data/public';
1718
import { EsHitRecord } from './context';
1819

@@ -27,31 +28,12 @@ export function fetchAnchorProvider(
2728
sort: EsQuerySortValue[]
2829
): Promise<EsHitRecord> {
2930
const indexPattern = await indexPatterns.get(indexPatternId);
30-
searchSource
31-
.setParent(undefined)
32-
.setField('index', indexPattern)
33-
.setField('version', true)
34-
.setField('size', 1)
35-
.setField('query', {
36-
query: {
37-
constant_score: {
38-
filter: {
39-
ids: {
40-
values: [anchorId],
41-
},
42-
},
43-
},
44-
},
45-
language: 'lucene',
46-
})
47-
.setField('sort', sort);
48-
if (useNewFieldsApi) {
49-
searchSource.removeField('fieldsFromSource');
50-
searchSource.setField('fields', [{ field: '*', include_unmapped: 'true' }]);
51-
}
31+
updateSearchSource(searchSource, anchorId, sort, useNewFieldsApi, indexPattern);
32+
5233
const response = await searchSource.fetch();
34+
const doc = get(response, ['hits', 'hits', 0]);
5335

54-
if (get(response, ['hits', 'total'], 0) < 1) {
36+
if (!doc) {
5537
throw new Error(
5638
i18n.translate('discover.context.failedToLoadAnchorDocumentErrorDescription', {
5739
defaultMessage: 'Failed to load anchor document.',
@@ -60,8 +42,41 @@ export function fetchAnchorProvider(
6042
}
6143

6244
return {
63-
...get(response, ['hits', 'hits', 0]),
45+
...doc,
6446
isAnchor: true,
6547
} as EsHitRecord;
6648
};
6749
}
50+
51+
export function updateSearchSource(
52+
searchSource: ISearchSource,
53+
anchorId: string,
54+
sort: EsQuerySortValue[],
55+
useNewFieldsApi: boolean,
56+
indexPattern: IndexPattern
57+
) {
58+
searchSource
59+
.setParent(undefined)
60+
.setField('index', indexPattern)
61+
.setField('version', true)
62+
.setField('size', 1)
63+
.setField('query', {
64+
query: {
65+
constant_score: {
66+
filter: {
67+
ids: {
68+
values: [anchorId],
69+
},
70+
},
71+
},
72+
},
73+
language: 'lucene',
74+
})
75+
.setField('sort', sort)
76+
.setField('trackTotalHits', false);
77+
if (useNewFieldsApi) {
78+
searchSource.removeField('fieldsFromSource');
79+
searchSource.setField('fields', [{ field: '*', include_unmapped: 'true' }]);
80+
}
81+
return searchSource;
82+
}

src/plugins/discover/public/application/angular/context/api/context.predecessors.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ interface Timestamp {
2727
lte?: string;
2828
}
2929

30-
describe('context app', function () {
30+
describe('context predecessors', function () {
3131
let fetchPredecessors: (
3232
indexPatternId: string,
3333
timeField: string,
@@ -49,7 +49,7 @@ describe('context app', function () {
4949
data: {
5050
search: {
5151
searchSource: {
52-
create: jest.fn().mockImplementation(() => mockSearchSource),
52+
createEmpty: jest.fn().mockImplementation(() => mockSearchSource),
5353
},
5454
},
5555
},
@@ -241,7 +241,7 @@ describe('context app', function () {
241241
data: {
242242
search: {
243243
searchSource: {
244-
create: jest.fn().mockImplementation(() => mockSearchSource),
244+
createEmpty: jest.fn().mockImplementation(() => mockSearchSource),
245245
},
246246
},
247247
},

src/plugins/discover/public/application/angular/context/api/context.successors.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ interface Timestamp {
2727
lte?: string;
2828
}
2929

30-
describe('context app', function () {
30+
describe('context successors', function () {
3131
let fetchSuccessors: (
3232
indexPatternId: string,
3333
timeField: string,
@@ -49,7 +49,7 @@ describe('context app', function () {
4949
data: {
5050
search: {
5151
searchSource: {
52-
create: jest.fn().mockImplementation(() => mockSearchSource),
52+
createEmpty: jest.fn().mockImplementation(() => mockSearchSource),
5353
},
5454
},
5555
},
@@ -244,7 +244,7 @@ describe('context app', function () {
244244
data: {
245245
search: {
246246
searchSource: {
247-
create: jest.fn().mockImplementation(() => mockSearchSource),
247+
createEmpty: jest.fn().mockImplementation(() => mockSearchSource),
248248
},
249249
},
250250
},
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the Elastic License
4+
* 2.0 and the Server Side Public License, v 1; you may not use this file except
5+
* in compliance with, at your election, the Elastic License 2.0 or the Server
6+
* Side Public License, v 1.
7+
*/
8+
9+
import { updateSearchSource } from './context';
10+
import { indexPatternMock } from '../../../../__mocks__/index_pattern';
11+
import { createSearchSourceMock } from '../../../../../../data/public/mocks';
12+
13+
describe('context api', function () {
14+
test('createSearchSource when useFieldsApi is true', () => {
15+
const newSearchSource = createSearchSourceMock({ index: indexPatternMock });
16+
const searchSource = updateSearchSource(newSearchSource, indexPatternMock, [], true);
17+
expect(searchSource.getSearchRequestBody()).toMatchSnapshot();
18+
});
19+
test('createSearchSource when useFieldsApi is false', () => {
20+
const newSearchSource = createSearchSourceMock({ index: indexPatternMock });
21+
const searchSource = updateSearchSource(newSearchSource, indexPatternMock, [], false);
22+
expect(searchSource.getSearchRequestBody()).toMatchSnapshot();
23+
});
24+
});

src/plugins/discover/public/application/angular/context/api/context.ts

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import type { estypes } from '@elastic/elasticsearch';
10-
import { Filter, IndexPatternsContract, IndexPattern } from 'src/plugins/data/public';
10+
import { Filter, IndexPatternsContract, IndexPattern, SearchSource } from 'src/plugins/data/public';
1111
import { reverseSortDir, SortDirection } from './utils/sorting';
1212
import { extractNanos, convertIsoToMillis } from './utils/date_conversion';
1313
import { fetchHitsInInterval } from './utils/fetch_hits_in_interval';
@@ -46,7 +46,7 @@ function fetchContextProvider(indexPatterns: IndexPatternsContract, useNewFields
4646
*
4747
* @param {SurrDocType} type - `successors` or `predecessors`
4848
* @param {string} indexPatternId
49-
* @param {AnchorHitRecord} anchor - anchor record
49+
* @param {EsHitRecord} anchor - anchor record
5050
* @param {string} timeField - name of the timefield, that's sorted on
5151
* @param {string} tieBreakerField - name of the tie breaker, the 2nd sort field
5252
* @param {SortDirection} sortDir - direction of sorting
@@ -68,7 +68,9 @@ function fetchContextProvider(indexPatterns: IndexPatternsContract, useNewFields
6868
return [];
6969
}
7070
const indexPattern = await indexPatterns.get(indexPatternId);
71-
const searchSource = await createSearchSource(indexPattern, filters);
71+
const { data } = getServices();
72+
const searchSource = data.search.searchSource.createEmpty() as SearchSource;
73+
updateSearchSource(searchSource, indexPattern, filters, Boolean(useNewFieldsApi));
7274
const sortDirToApply = type === SurrDocType.SUCCESSORS ? sortDir : reverseSortDir(sortDir);
7375

7476
const nanos = indexPattern.isTimeNanosBased() ? extractNanos(anchor.fields[timeField][0]) : '';
@@ -116,20 +118,23 @@ function fetchContextProvider(indexPatterns: IndexPatternsContract, useNewFields
116118

117119
return documents;
118120
}
121+
}
119122

120-
async function createSearchSource(indexPattern: IndexPattern, filters: Filter[]) {
121-
const { data } = getServices();
122-
123-
const searchSource = await data.search.searchSource.create();
124-
if (useNewFieldsApi) {
125-
searchSource.removeField('fieldsFromSource');
126-
searchSource.setField('fields', [{ field: '*', include_unmapped: 'true' }]);
127-
}
128-
return searchSource
129-
.setParent(undefined)
130-
.setField('index', indexPattern)
131-
.setField('filter', filters);
123+
export function updateSearchSource(
124+
searchSource: SearchSource,
125+
indexPattern: IndexPattern,
126+
filters: Filter[],
127+
useNewFieldsApi: boolean
128+
) {
129+
if (useNewFieldsApi) {
130+
searchSource.removeField('fieldsFromSource');
131+
searchSource.setField('fields', [{ field: '*', include_unmapped: 'true' }]);
132132
}
133+
return searchSource
134+
.setParent(undefined)
135+
.setField('index', indexPattern)
136+
.setField('filter', filters)
137+
.setField('trackTotalHits', false);
133138
}
134139

135140
export { fetchContextProvider };

0 commit comments

Comments
 (0)