-
Notifications
You must be signed in to change notification settings - Fork 8.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[OnWeek][Discover] Allow to fetch more documents on Discover page #157241
Changes from 52 commits
4e80b82
c07d672
e4e1269
3d26f8a
d218e6e
3254b98
0c867cf
e868a12
bead1dc
d2c26f9
f4575d7
f9adfa1
e6a9453
46a7a13
b11ed0a
87f57d3
200b978
0b951e9
d89ec6b
bc57946
e10c82c
32653ea
e38495a
02124f9
a75d3cd
f7759a3
d50cd7e
ebadf47
8c5f2f2
08281ea
13d5b0a
5da6f3f
c193c64
c73ef31
556b284
b2d4ba6
e3555f7
ef34510
2b97c3d
6be7240
76f1cfe
e3c2d83
2a8fefa
a57eafa
5d10203
a72bd08
358c755
5413e5e
a2cb79f
c8728d4
8d63088
bb5bd8a
2fb0eab
2d301a3
334fcb8
25a19fd
77ea97e
a2b8a72
3d336b9
3f9bdac
f0dfe07
f780097
5a9f68f
a29238b
5cd37d2
17448a0
5230557
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
/* | ||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||
* or more contributor license agreements. Licensed under the Elastic License | ||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||
* Side Public License, v 1. | ||
*/ | ||
|
||
import { SortDirection } from '@kbn/data-plugin/common'; | ||
import { createStubDataView } from '@kbn/data-views-plugin/common/data_view.stub'; | ||
import { | ||
getEsQuerySort, | ||
getESQuerySortForTieBreaker, | ||
getESQuerySortForTimeField, | ||
getTieBreakerFieldName, | ||
} from './get_es_query_sort'; | ||
import { CONTEXT_TIE_BREAKER_FIELDS_SETTING } from '@kbn/discover-utils'; | ||
import { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; | ||
|
||
const dataView = createStubDataView({ | ||
spec: { | ||
id: 'logstash-*', | ||
fields: { | ||
test_field: { | ||
name: 'test_field', | ||
type: 'string', | ||
esTypes: ['keyword'], | ||
aggregatable: true, | ||
searchable: true, | ||
}, | ||
test_field_not_sortable: { | ||
name: 'test_field_not_sortable', | ||
type: 'string', | ||
esTypes: ['keyword'], | ||
aggregatable: false, | ||
searchable: false, | ||
}, | ||
}, | ||
title: 'logstash-*', | ||
timeFieldName: '@timestamp', | ||
}, | ||
}); | ||
|
||
describe('get_es_query_sort', function () { | ||
test('getEsQuerySort should return sort params', function () { | ||
expect( | ||
getEsQuerySort({ | ||
sortDir: SortDirection.desc, | ||
timeFieldName: 'testTimeField', | ||
isTimeNanosBased: false, | ||
tieBreakerFieldName: 'testTieBreakerField', | ||
}) | ||
).toStrictEqual([ | ||
{ testTimeField: { format: 'strict_date_optional_time', order: 'desc' } }, | ||
{ testTieBreakerField: 'desc' }, | ||
]); | ||
|
||
expect( | ||
getEsQuerySort({ | ||
sortDir: SortDirection.asc, | ||
timeFieldName: 'testTimeField', | ||
isTimeNanosBased: true, | ||
tieBreakerFieldName: 'testTieBreakerField', | ||
}) | ||
).toStrictEqual([ | ||
{ | ||
testTimeField: { | ||
format: 'strict_date_optional_time_nanos', | ||
numeric_type: 'date_nanos', | ||
order: 'asc', | ||
}, | ||
}, | ||
{ testTieBreakerField: 'asc' }, | ||
]); | ||
}); | ||
|
||
test('getESQuerySortForTimeField should return time field as sort param', function () { | ||
expect( | ||
getESQuerySortForTimeField({ | ||
sortDir: SortDirection.desc, | ||
timeFieldName: 'testTimeField', | ||
isTimeNanosBased: false, | ||
}) | ||
).toStrictEqual({ | ||
testTimeField: { | ||
format: 'strict_date_optional_time', | ||
order: 'desc', | ||
}, | ||
}); | ||
|
||
expect( | ||
getESQuerySortForTimeField({ | ||
sortDir: SortDirection.asc, | ||
timeFieldName: 'testTimeField', | ||
isTimeNanosBased: true, | ||
}) | ||
).toStrictEqual({ | ||
testTimeField: { | ||
format: 'strict_date_optional_time_nanos', | ||
numeric_type: 'date_nanos', | ||
order: 'asc', | ||
}, | ||
}); | ||
}); | ||
|
||
test('getESQuerySortForTieBreaker should return tie breaker as sort param', function () { | ||
expect( | ||
getESQuerySortForTieBreaker({ | ||
sortDir: SortDirection.desc, | ||
tieBreakerFieldName: 'testTieBreaker', | ||
}) | ||
).toStrictEqual({ testTieBreaker: 'desc' }); | ||
}); | ||
|
||
test('getTieBreakerFieldName should return a correct tie breaker', function () { | ||
expect( | ||
getTieBreakerFieldName(dataView, { | ||
get: (key) => (key === CONTEXT_TIE_BREAKER_FIELDS_SETTING ? ['_doc'] : undefined), | ||
} as IUiSettingsClient) | ||
).toBe('_doc'); | ||
|
||
expect( | ||
getTieBreakerFieldName(dataView, { | ||
get: (key) => | ||
key === CONTEXT_TIE_BREAKER_FIELDS_SETTING | ||
? ['test_field_not_sortable', '_doc'] | ||
: undefined, | ||
} as IUiSettingsClient) | ||
).toBe('_doc'); | ||
|
||
expect( | ||
getTieBreakerFieldName(dataView, { | ||
get: (key) => | ||
key === CONTEXT_TIE_BREAKER_FIELDS_SETTING ? ['test_field', '_doc'] : undefined, | ||
} as IUiSettingsClient) | ||
).toBe('test_field'); | ||
|
||
expect( | ||
getTieBreakerFieldName(dataView, { | ||
get: (key) => undefined, | ||
} as IUiSettingsClient) | ||
).toBeUndefined(); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
@@ -0,0 +1,107 @@ | ||||
/* | ||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one | ||||
* or more contributor license agreements. Licensed under the Elastic License | ||||
* 2.0 and the Server Side Public License, v 1; you may not use this file except | ||||
* in compliance with, at your election, the Elastic License 2.0 or the Server | ||||
* Side Public License, v 1. | ||||
*/ | ||||
|
||||
import type { EsQuerySortValue, SortDirection } from '@kbn/data-plugin/public'; | ||||
import type { DataView } from '@kbn/data-views-plugin/common'; | ||||
import type { IUiSettingsClient } from '@kbn/core-ui-settings-browser'; | ||||
import { CONTEXT_TIE_BREAKER_FIELDS_SETTING } from '@kbn/discover-utils'; | ||||
|
||||
/** | ||||
* Returns `EsQuerySort` which is used to sort records in the ES query | ||||
* https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html | ||||
* @param sortDir | ||||
* @param timeFieldName | ||||
* @param tieBreakerFieldName | ||||
* @param isTimeNanosBased | ||||
*/ | ||||
export function getEsQuerySort({ | ||||
sortDir, | ||||
timeFieldName, | ||||
tieBreakerFieldName, | ||||
isTimeNanosBased, | ||||
}: { | ||||
sortDir: SortDirection; | ||||
timeFieldName: string; | ||||
tieBreakerFieldName: string; | ||||
isTimeNanosBased: boolean; | ||||
}): [EsQuerySortValue, EsQuerySortValue] { | ||||
return [ | ||||
getESQuerySortForTimeField({ sortDir, timeFieldName, isTimeNanosBased }), | ||||
getESQuerySortForTieBreaker({ sortDir, tieBreakerFieldName }), | ||||
]; | ||||
} | ||||
|
||||
/** | ||||
* Prepares "sort" structure for a time field for next ES request | ||||
* @param sortDir | ||||
* @param timeFieldName | ||||
* @param isTimeNanosBased | ||||
*/ | ||||
export function getESQuerySortForTimeField({ | ||||
sortDir, | ||||
timeFieldName, | ||||
isTimeNanosBased, | ||||
}: { | ||||
sortDir: SortDirection; | ||||
timeFieldName: string; | ||||
isTimeNanosBased: boolean; | ||||
}): EsQuerySortValue { | ||||
return { | ||||
[timeFieldName]: { | ||||
order: sortDir, | ||||
...(isTimeNanosBased | ||||
? { | ||||
format: 'strict_date_optional_time_nanos', | ||||
numeric_type: 'date_nanos', | ||||
} | ||||
: { format: 'strict_date_optional_time' }), | ||||
}, | ||||
}; | ||||
} | ||||
|
||||
/** | ||||
* Prepares "sort" structure for a tie breaker for next ES request | ||||
* @param sortDir | ||||
* @param tieBreakerFieldName | ||||
*/ | ||||
export function getESQuerySortForTieBreaker({ | ||||
sortDir, | ||||
tieBreakerFieldName, | ||||
}: { | ||||
sortDir: SortDirection; | ||||
tieBreakerFieldName: string; | ||||
}): EsQuerySortValue { | ||||
return { [tieBreakerFieldName]: sortDir }; | ||||
} | ||||
|
||||
/** | ||||
* The default tie breaker for Discover | ||||
*/ | ||||
export const DEFAULT_TIE_BREAKER_NAME = '_doc'; | ||||
|
||||
/** | ||||
* The list of field names that are allowed for sorting, but not included in | ||||
* data view fields. | ||||
*/ | ||||
const META_FIELD_NAMES: string[] = ['_seq_no', '_doc', '_uid']; | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wonder if The documentation recommends using PIT with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @weltenwort Thanks for bring our attention to this! I have not introduced this array, just moved from context utils to common utils. For supporting legacy behaviour, I think we should keep There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we can only use There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
wouldn't
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would work, it might just lead to duplicate rows sometimes when shard merges occur. For the Logs UI that's a trade-off that we accepted. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this trade-off is fine There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the feedback on this! I agree that the tradeoff should be fine for us too. |
||||
|
||||
/** | ||||
* Returns a field from the intersection of the set of sortable fields in the | ||||
* given data view and a given set of candidate field names. | ||||
*/ | ||||
export function getTieBreakerFieldName( | ||||
dataView: DataView, | ||||
uiSettings: Pick<IUiSettingsClient, 'get'> | ||||
) { | ||||
const sortableFields = (uiSettings.get(CONTEXT_TIE_BREAKER_FIELDS_SETTING) || []).filter( | ||||
(fieldName: string) => | ||||
META_FIELD_NAMES.includes(fieldName) || | ||||
(dataView.fields.getByName(fieldName) || { sortable: false }).sortable | ||||
); | ||||
return sortableFields[0]; | ||||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I checked about the impact for loading 10000 documents.
It's not surprising, the used memory of the Browser is increasing significantly when loading 10000 documents incrementally. But for my working machine, a MacBook Pro, 2021, 32 GB, this ain't an issue. For sure this can get much slower depending on the machine spec.
I've been using my iPhone SE 2, to test it. It is no a pleasure to use Discover with this machine, but when I reached the end of those 10000 documents being loaded ... the UI was snappy.
Give we also allow the configuration of a 10000 sample size, which also worked for me: LGTM