Skip to content

Commit

Permalink
[Discover/CSV Reporting] Fix support for nested field columns in CSV …
Browse files Browse the repository at this point in the history
…reports (elastic#172240)

## Summary

When we generate the parameters for the report, we add all of the
selected columns as entries in the search request `fields` array (or `*`
if none are selected, which is why this case works), but this doesn't
work for nested fields since [the fields API doesn't support nested
field
roots](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-fields.html#search-fields-nested):
>However, when the `fields` pattern targets the nested `user` field
directly, no values will be returned because the pattern doesn’t match
any leaf fields.

Instead we can detect nested fields and add them to the `fields` array
as `{nestedFieldName}.*`, ensuring that all of the leaf fields are
returned in the response.

Fixes elastic#172236.

### Checklist

- [ ] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [ ]
[Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html)
was added for features that require explanation or tutorials
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [ ] Any UI touched in this PR is usable by keyboard only (learn more
about [keyboard accessibility](https://webaim.org/techniques/keyboard/))
- [ ] Any UI touched in this PR does not create any new axe failures
(run axe in browser:
[FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/),
[Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US))
- [ ] If a plugin configuration key changed, check if it needs to be
allowlisted in the cloud and added to the [docker
list](https://github.com/elastic/kibana/blob/main/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker)
- [ ] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [ ] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)

### For maintainers

- [ ] This was checked for breaking API changes and was [labeled
appropriately](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)

---------

Co-authored-by: kibanamachine <[email protected]>
(cherry picked from commit ab5ff9c)

# Conflicts:
#	src/plugins/discover/public/application/apps/main/utils/get_sharing_data.test.ts
#	src/plugins/discover/public/application/apps/main/utils/get_sharing_data.ts
#	x-pack/plugins/reporting/tsconfig.json
  • Loading branch information
davismcphee committed Dec 1, 2023
1 parent 94b0573 commit ea61476
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
SEARCH_FIELDS_FROM_SOURCE,
} from '../../../../../common';
import { indexPatternMock } from '../../../../__mocks__/index_pattern';
import { buildDataViewMock, dataViewMock } from '@kbn/discover-utils/src/__mocks__';
import { getSharingData, showPublicUrlSwitch } from './get_sharing_data';

describe('getSharingData', () => {
Expand Down Expand Up @@ -147,6 +148,38 @@ describe('getSharingData', () => {
);
expect(getSearchSource().fields).toStrictEqual([
'cool-timefield',
]);
});

test('getSearchSource supports nested fields', async () => {
const index = buildDataViewMock({
name: 'the-data-view',
timeFieldName: 'cool-timefield',
fields: [
...dataViewMock.fields,
{
name: 'cool-field-2.field',
type: 'keyword',
subType: {
nested: {
path: 'cool-field-2.field.path',
},
},
},
] as DataView['fields'],
});
const searchSourceMock = createSearchSourceMock({ index });
const { getSearchSource } = await getSharingData(
searchSourceMock,
{
columns: ['cool-field-1', 'cool-field-2'],
},
services
);
expect(getSearchSource({}).fields).toStrictEqual([
{ field: 'cool-timefield', include_unmapped: 'true' },
{ field: 'cool-field-1', include_unmapped: 'true' },
{ field: 'cool-field-2.*', include_unmapped: 'true' },
'cool-field-1',
'cool-field-2',
'cool-field-3',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type { DataPublicPluginStart } from 'src/plugins/data/public';
import type { Filter, ISearchSource, SearchSourceFields } from 'src/plugins/data/common';
import {
DOC_HIDE_TIME_COLUMN_SETTING,
isNestedFieldParent,
SORT_DEFAULT_ORDER_SETTING,
SEARCH_FIELDS_FROM_SOURCE,
} from '../../../../../common';
Expand Down Expand Up @@ -93,6 +94,21 @@ export async function getSharingData(
const useFieldsApi = !config.get(SEARCH_FIELDS_FROM_SOURCE);
if (useFieldsApi && columns.length) {
searchSource.setField('fields', columns);
const useFieldsApi = !uiSettings.get(SEARCH_FIELDS_FROM_SOURCE);
if (useFieldsApi) {
searchSource.removeField('fieldsFromSource');
const fields = columns.length
? columns.map((column) => {
let field = column;

// If this column is a nested field, add a wildcard to the field name in order to fetch
// all leaf fields for the report, since the fields API doesn't support nested field roots
if (isNestedFieldParent(column, index)) {
field = `${column}.*`;
}

return { field, include_unmapped: 'true' };
})
}
return searchSource.getSerializedFields(true);
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { ReportingAPIClient } from '../lib/reporting_api_client';
import type { ReportingPublicPluginStartDendencies } from '../plugin';
import type { ActionContext } from './get_csv_panel_action';
import { ReportingCsvPanelAction } from './get_csv_panel_action';
import { dataViewMock } from '@kbn/discover-utils/src/__mocks__';

type LicenseResults = 'valid' | 'invalid' | 'unavailable' | 'expired';

Expand Down Expand Up @@ -119,7 +120,7 @@ describe('GetCsvReportPanelAction', () => {
createCopy: () => mockSearchSource,
removeField: jest.fn(),
setField: jest.fn(),
getField: jest.fn(),
getField: jest.fn((name) => (name === 'index' ? dataViewMock : undefined)),
getSerializedFields: jest.fn().mockImplementation(() => ({ testData: 'testDataValue' })),
} as unknown as SearchSource;
context.embeddable.getSavedSearch = () => {
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/reporting/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"public/**/*",
"server/**/*",
"../../../typings/**/*"
"@kbn/discover-utils",
],
"references": [
{ "path": "../../../src/core/tsconfig.json" },
Expand Down

0 comments on commit ea61476

Please sign in to comment.