[Maps] term join limit (#86491)
* [Maps] term join limit * update region map migration to set size * display size in join expression * tslint * update jest snapshots * remove default size and just default to max buckets * add size to sourceMeta so join data is re-requested on size change * tslint Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
6c87222e67
commit
8a0c8f35bd
|
@ -71,6 +71,7 @@ export function getDeprecationMessage(vis: Vis) {
|
|||
const bucketAggs = vis.data?.aggs?.byType('buckets');
|
||||
if (bucketAggs?.length && bucketAggs[0].type.dslName === 'terms') {
|
||||
createUrlParams.termsFieldName = bucketAggs[0].getField()?.name;
|
||||
createUrlParams.termsSize = bucketAggs[0].getParam('size');
|
||||
}
|
||||
|
||||
const metricAggs = vis.data?.aggs?.byType('metrics');
|
||||
|
|
|
@ -39,10 +39,15 @@ type ESGeoLineSourceSyncMeta = {
|
|||
sortField: string;
|
||||
};
|
||||
|
||||
type ESTermSourceSyncMeta = {
|
||||
size: number;
|
||||
};
|
||||
|
||||
export type VectorSourceSyncMeta =
|
||||
| ESSearchSourceSyncMeta
|
||||
| ESGeoGridSourceSyncMeta
|
||||
| ESGeoLineSourceSyncMeta
|
||||
| ESTermSourceSyncMeta
|
||||
| null;
|
||||
|
||||
export type VectorSourceRequestMeta = MapFilters & {
|
||||
|
@ -54,10 +59,9 @@ export type VectorSourceRequestMeta = MapFilters & {
|
|||
sourceMeta: VectorSourceSyncMeta;
|
||||
};
|
||||
|
||||
export type VectorJoinSourceRequestMeta = Omit<
|
||||
VectorSourceRequestMeta,
|
||||
'geogridPrecision' | 'sourceMeta'
|
||||
> & { sourceQuery?: Query };
|
||||
export type VectorJoinSourceRequestMeta = Omit<VectorSourceRequestMeta, 'geogridPrecision'> & {
|
||||
sourceQuery?: Query;
|
||||
};
|
||||
|
||||
export type VectorStyleRequestMeta = MapFilters & {
|
||||
dynamicStyleFields: string[];
|
||||
|
|
|
@ -104,6 +104,7 @@ export type ESTermSourceDescriptor = AbstractESAggSourceDescriptor & {
|
|||
indexPatternTitle?: string;
|
||||
term: string; // term field name
|
||||
whereQuery?: Query;
|
||||
size?: number;
|
||||
};
|
||||
|
||||
export type KibanaRegionmapSourceDescriptor = AbstractSourceDescriptor & {
|
||||
|
|
|
@ -8,6 +8,7 @@ import uuid from 'uuid/v4';
|
|||
import {
|
||||
AggDescriptor,
|
||||
ColorDynamicOptions,
|
||||
ESTermSourceDescriptor,
|
||||
LayerDescriptor,
|
||||
} from '../../../common/descriptor_types';
|
||||
import {
|
||||
|
@ -48,6 +49,7 @@ export function createRegionMapLayerDescriptor({
|
|||
emsLayerId,
|
||||
leftFieldName,
|
||||
termsFieldName,
|
||||
termsSize,
|
||||
colorSchema,
|
||||
indexPatternId,
|
||||
indexPatternTitle,
|
||||
|
@ -58,6 +60,7 @@ export function createRegionMapLayerDescriptor({
|
|||
emsLayerId?: string;
|
||||
leftFieldName?: string;
|
||||
termsFieldName?: string;
|
||||
termsSize?: number;
|
||||
colorSchema: string;
|
||||
indexPatternId?: string;
|
||||
indexPatternTitle?: string;
|
||||
|
@ -78,21 +81,25 @@ export function createRegionMapLayerDescriptor({
|
|||
const colorPallette = NUMERICAL_COLOR_PALETTES.find((pallette) => {
|
||||
return pallette.value.toLowerCase() === colorSchema.toLowerCase();
|
||||
});
|
||||
const termSourceDescriptor: ESTermSourceDescriptor = {
|
||||
type: SOURCE_TYPES.ES_TERM_SOURCE,
|
||||
id: joinId,
|
||||
indexPatternId,
|
||||
indexPatternTitle: indexPatternTitle ? indexPatternTitle : indexPatternId,
|
||||
term: termsFieldName,
|
||||
metrics: [metricsDescriptor],
|
||||
applyGlobalQuery: true,
|
||||
applyGlobalTime: true,
|
||||
};
|
||||
if (termsSize !== undefined) {
|
||||
termSourceDescriptor.size = termsSize;
|
||||
}
|
||||
return VectorLayer.createDescriptor({
|
||||
label,
|
||||
joins: [
|
||||
{
|
||||
leftField: leftFieldName,
|
||||
right: {
|
||||
type: SOURCE_TYPES.ES_TERM_SOURCE,
|
||||
id: joinId,
|
||||
indexPatternId,
|
||||
indexPatternTitle: indexPatternTitle ? indexPatternTitle : indexPatternId,
|
||||
term: termsFieldName,
|
||||
metrics: [metricsDescriptor],
|
||||
applyGlobalQuery: true,
|
||||
applyGlobalTime: true,
|
||||
},
|
||||
right: termSourceDescriptor,
|
||||
},
|
||||
],
|
||||
sourceDescriptor: EMSFileSource.createDescriptor({
|
||||
|
|
|
@ -349,6 +349,7 @@ export class VectorLayer extends AbstractLayer {
|
|||
sourceQuery: joinSource.getWhereQuery(),
|
||||
applyGlobalQuery: joinSource.getApplyGlobalQuery(),
|
||||
applyGlobalTime: joinSource.getApplyGlobalTime(),
|
||||
sourceMeta: joinSource.getSyncMeta(),
|
||||
};
|
||||
const prevDataRequest = this.getDataRequest(sourceDataId);
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ import {
|
|||
import {
|
||||
ESTermSourceDescriptor,
|
||||
VectorJoinSourceRequestMeta,
|
||||
VectorSourceSyncMeta,
|
||||
} from '../../../../common/descriptor_types';
|
||||
import { Adapters } from '../../../../../../../src/plugins/inspector/common/adapters';
|
||||
import { PropertiesMap } from '../../../../common/elasticsearch_util';
|
||||
|
@ -124,7 +125,9 @@ export class ESTermSource extends AbstractESAggSource {
|
|||
const indexPattern = await this.getIndexPattern();
|
||||
const searchSource: ISearchSource = await this.makeSearchSource(searchFilters, 0);
|
||||
const termsField = getField(indexPattern, this._termField.getName());
|
||||
const termsAgg = { size: DEFAULT_MAX_BUCKETS_LIMIT };
|
||||
const termsAgg = {
|
||||
size: this._descriptor.size !== undefined ? this._descriptor.size : DEFAULT_MAX_BUCKETS_LIMIT,
|
||||
};
|
||||
searchSource.setField('aggs', {
|
||||
[TERMS_AGG_NAME]: {
|
||||
terms: addFieldToDSL(termsAgg, termsField),
|
||||
|
@ -162,4 +165,12 @@ export class ESTermSource extends AbstractESAggSource {
|
|||
getFieldNames(): string[] {
|
||||
return this.getMetricFields().map((esAggMetricField) => esAggMetricField.getName());
|
||||
}
|
||||
|
||||
getSyncMeta(): VectorSourceSyncMeta | null {
|
||||
return this._descriptor.size !== undefined
|
||||
? {
|
||||
size: this._descriptor.size,
|
||||
}
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
exports[`should render with error 1`] = `
|
||||
<EuiFormRow
|
||||
describedByIds={Array []}
|
||||
display="columnCompressed"
|
||||
display="row"
|
||||
error={
|
||||
Array [
|
||||
"Must be between 0 and 20",
|
||||
|
@ -30,7 +30,7 @@ exports[`should render with error 1`] = `
|
|||
exports[`should render without error 1`] = `
|
||||
<EuiFormRow
|
||||
describedByIds={Array []}
|
||||
display="columnCompressed"
|
||||
display="row"
|
||||
error={Array []}
|
||||
fullWidth={false}
|
||||
hasChildLabel={true}
|
||||
|
|
|
@ -154,6 +154,7 @@ export function MetricEditor({
|
|||
initialValue={
|
||||
typeof metric.percentile === 'number' ? metric.percentile : DEFAULT_PERCENTILE
|
||||
}
|
||||
display="columnCompressed"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -4,8 +4,9 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import React, { Component, ChangeEvent } from 'react';
|
||||
import { EuiFieldNumber, EuiFormRow } from '@elastic/eui';
|
||||
import React, { Component, ChangeEvent, ReactNode } from 'react';
|
||||
// @ts-expect-error
|
||||
import { EuiFieldNumber, EuiFormRow, EuiFormRowDisplayKeys } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import _ from 'lodash';
|
||||
|
||||
|
@ -21,6 +22,8 @@ interface Props {
|
|||
max: number;
|
||||
onChange: (value: number) => void;
|
||||
label: string;
|
||||
display?: EuiFormRowDisplayKeys;
|
||||
helpText?: ReactNode;
|
||||
}
|
||||
|
||||
function getErrorMessage(min: number, max: number): string {
|
||||
|
@ -97,7 +100,8 @@ export class ValidatedNumberInput extends Component<Props, State> {
|
|||
label={this.props.label}
|
||||
isInvalid={!this.state.isValid}
|
||||
error={this.state.errorMessage ? [this.state.errorMessage] : []}
|
||||
display="columnCompressed"
|
||||
display={this.props.display}
|
||||
helpText={this.props.helpText}
|
||||
>
|
||||
<EuiFieldNumber
|
||||
isInvalid={!this.state.isValid}
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
*/
|
||||
|
||||
import React, { Fragment } from 'react';
|
||||
import _ from 'lodash';
|
||||
import uuid from 'uuid/v4';
|
||||
|
||||
import {
|
||||
|
|
|
@ -19,7 +19,6 @@ exports[`Should render default props 1`] = `
|
|||
isOpen={false}
|
||||
ownFocus={true}
|
||||
panelPaddingSize="m"
|
||||
withTitle={true}
|
||||
>
|
||||
<div
|
||||
style={
|
||||
|
@ -74,7 +73,6 @@ exports[`Should render metrics expression for metrics 1`] = `
|
|||
isOpen={false}
|
||||
ownFocus={true}
|
||||
panelPaddingSize="m"
|
||||
withTitle={true}
|
||||
>
|
||||
<div
|
||||
style={
|
||||
|
|
|
@ -77,10 +77,12 @@ export class Join extends Component {
|
|||
loadError: undefined,
|
||||
});
|
||||
this._loadRightFields(indexPatternId);
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
const { term, ...restOfRight } = this.props.join.right;
|
||||
this.props.onChange({
|
||||
leftField: this.props.join.leftField,
|
||||
right: {
|
||||
id: this.props.join.right.id,
|
||||
...restOfRight,
|
||||
indexPatternId,
|
||||
indexPatternTitle,
|
||||
},
|
||||
|
@ -97,6 +99,16 @@ export class Join extends Component {
|
|||
});
|
||||
};
|
||||
|
||||
_onRightSizeChange = (size) => {
|
||||
this.props.onChange({
|
||||
leftField: this.props.join.leftField,
|
||||
right: {
|
||||
...this.props.join.right,
|
||||
size,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
_onMetricsChange = (metrics) => {
|
||||
this.props.onChange({
|
||||
leftField: this.props.join.leftField,
|
||||
|
@ -161,7 +173,7 @@ export class Join extends Component {
|
|||
);
|
||||
globalFilterCheckbox = (
|
||||
<GlobalFilterCheckbox
|
||||
applyGlobalQuery={right.applyGlobalQuery}
|
||||
applyGlobalQuery={right.applyGlobalQuery === 'undefined' ? true : right.applyGlobalQuery}
|
||||
setApplyGlobalQuery={this._onApplyGlobalQueryChange}
|
||||
label={i18n.translate('xpack.maps.layerPanel.join.applyGlobalQueryCheckboxLabel', {
|
||||
defaultMessage: `Apply global filter to join`,
|
||||
|
@ -209,8 +221,10 @@ export class Join extends Component {
|
|||
rightSourceName={rightSourceName}
|
||||
onRightSourceChange={this._onRightSourceChange}
|
||||
rightValue={right.term}
|
||||
rightSize={right.size}
|
||||
rightFields={rightFields}
|
||||
onRightFieldChange={this._onRightFieldChange}
|
||||
onRightSizeChange={this._onRightSizeChange}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
|
||||
|
|
|
@ -17,7 +17,9 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { DEFAULT_MAX_BUCKETS_LIMIT } from '../../../../../common/constants';
|
||||
import { SingleFieldSelect } from '../../../../components/single_field_select';
|
||||
import { ValidatedNumberInput } from '../../../../components/validated_number_input';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
|
||||
import { getTermsFields } from '../../../../index_pattern_util';
|
||||
|
@ -155,10 +157,49 @@ export class JoinExpression extends Component {
|
|||
);
|
||||
}
|
||||
|
||||
_renderRightFieldSizeInput() {
|
||||
if (!this.props.rightValue || !this.props.leftValue) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<ValidatedNumberInput
|
||||
initialValue={
|
||||
this.props.rightSize !== undefined ? this.props.rightSize : DEFAULT_MAX_BUCKETS_LIMIT
|
||||
}
|
||||
min={1}
|
||||
max={DEFAULT_MAX_BUCKETS_LIMIT}
|
||||
onChange={this.props.onRightSizeChange}
|
||||
label={i18n.translate('xpack.maps.layerPanel.joinExpression.rightSizeLabel', {
|
||||
defaultMessage: 'Right size',
|
||||
})}
|
||||
helpText={i18n.translate('xpack.maps.layerPanel.joinExpression.rightSizeHelpText', {
|
||||
defaultMessage: 'Right field term limit.',
|
||||
})}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
_getExpressionValue() {
|
||||
const { leftSourceName, leftValue, rightSourceName, rightValue } = this.props;
|
||||
const { leftSourceName, leftValue, rightSourceName, rightValue, rightSize } = this.props;
|
||||
if (leftSourceName && leftValue && rightSourceName && rightValue) {
|
||||
return `${leftSourceName}:${leftValue} with ${rightSourceName}:${rightValue}`;
|
||||
return i18n.translate('xpack.maps.layerPanel.joinExpression.value', {
|
||||
defaultMessage:
|
||||
'{leftSourceName}:{leftValue} with {sizeFragment} {rightSourceName}:{rightValue}',
|
||||
values: {
|
||||
leftSourceName,
|
||||
leftValue,
|
||||
sizeFragment:
|
||||
rightSize !== undefined
|
||||
? i18n.translate('xpack.maps.layerPanel.joinExpression.sizeFragment', {
|
||||
defaultMessage: 'top {rightSize} terms from',
|
||||
values: { rightSize },
|
||||
})
|
||||
: '',
|
||||
rightSourceName,
|
||||
rightValue,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return i18n.translate('xpack.maps.layerPanel.joinExpression.selectPlaceholder', {
|
||||
|
@ -213,6 +254,8 @@ export class JoinExpression extends Component {
|
|||
{this._renderRightSourceSelect()}
|
||||
|
||||
{this._renderRightFieldSelect()}
|
||||
|
||||
{this._renderRightFieldSizeInput()}
|
||||
</div>
|
||||
</EuiPopover>
|
||||
);
|
||||
|
@ -240,8 +283,10 @@ JoinExpression.propTypes = {
|
|||
|
||||
// Right field props
|
||||
rightValue: PropTypes.string,
|
||||
rightSize: PropTypes.number,
|
||||
rightFields: PropTypes.array,
|
||||
onRightFieldChange: PropTypes.func.isRequired,
|
||||
onRightSizeChange: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
function getSelectFieldPlaceholder() {
|
||||
|
|
|
@ -93,7 +93,6 @@ export class MetricsExpression extends Component {
|
|||
closePopover={this._closePopover}
|
||||
ownFocus
|
||||
initialFocus="body" /* avoid initialFocus on Combobox */
|
||||
withTitle
|
||||
anchorPosition="leftCenter"
|
||||
button={
|
||||
<EuiExpression
|
||||
|
|
|
@ -52,6 +52,7 @@ interface LazyLoadedMapModules {
|
|||
emsLayerId,
|
||||
leftFieldName,
|
||||
termsFieldName,
|
||||
termsSize,
|
||||
colorSchema,
|
||||
indexPatternId,
|
||||
indexPatternTitle,
|
||||
|
@ -62,6 +63,7 @@ interface LazyLoadedMapModules {
|
|||
emsLayerId?: string;
|
||||
leftFieldName?: string;
|
||||
termsFieldName?: string;
|
||||
termsSize?: number;
|
||||
colorSchema: string;
|
||||
indexPatternId?: string;
|
||||
indexPatternTitle?: string;
|
||||
|
|
|
@ -183,6 +183,7 @@ export const createRegionMapUrlGenerator = (
|
|||
emsLayerId,
|
||||
leftFieldName,
|
||||
termsFieldName,
|
||||
termsSize,
|
||||
colorSchema,
|
||||
indexPatternId,
|
||||
indexPatternTitle,
|
||||
|
@ -197,6 +198,7 @@ export const createRegionMapUrlGenerator = (
|
|||
emsLayerId?: string;
|
||||
leftFieldName?: string;
|
||||
termsFieldName?: string;
|
||||
termsSize?: number;
|
||||
colorSchema: string;
|
||||
indexPatternId?: string;
|
||||
indexPatternTitle?: string;
|
||||
|
@ -214,6 +216,7 @@ export const createRegionMapUrlGenerator = (
|
|||
emsLayerId,
|
||||
leftFieldName,
|
||||
termsFieldName,
|
||||
termsSize,
|
||||
colorSchema,
|
||||
indexPatternId,
|
||||
indexPatternTitle,
|
||||
|
|
Loading…
Reference in a new issue