[Maps] Move sort out of top hits configuration for ES documents source (#47361)

* [Maps] Move sort out of top hits configuration for ES documents source

* add migration script to convert topHitsTimeField to sortField

* update i18n translations

* add jest test for es docs source UpdateSourceEditor component

* remove time configuration from top hits docs

* update migrations integration expect statement

* review feedback

* reverse hits list so top documents by sort are drawn on top

* update functional test expect to account for reversing hits order

* update another functional test expect clause for reversing hits
This commit is contained in:
Nathan Reese 2019-10-09 10:26:44 -06:00 committed by GitHub
parent 8936e21a3c
commit c17081ad4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 568 additions and 92 deletions

View file

@ -36,8 +36,6 @@ To enable most recent entities, click "Show most recent documents by entity" and
. Set *Entity* to the field that identifies entities in your documents.
This field will be used in the terms aggregation to group your documents into entity buckets.
. Set *Time* to the date field that puts your documents in chronological order.
This field will be used to sort your documents in the top hits aggregation.
. Set *Documents per entity* to configure the maximum number of documents accumulated per entity.
[role="xpack"]

View file

@ -39,6 +39,11 @@ export const LAYER_TYPE = {
HEATMAP: 'HEATMAP'
};
export const SORT_ORDER = {
ASC: 'asc',
DESC: 'desc',
};
export const EMS_TMS = 'EMS_TMS';
export const EMS_FILE = 'EMS_FILE';
export const ES_GEO_GRID = 'ES_GEO_GRID';

View file

@ -0,0 +1,35 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import _ from 'lodash';
import { ES_SEARCH, SORT_ORDER } from '../constants';
function isEsDocumentSource(layerDescriptor) {
const sourceType = _.get(layerDescriptor, 'sourceDescriptor.type');
return sourceType === ES_SEARCH;
}
export function topHitsTimeToSort({ attributes }) {
if (!attributes.layerListJSON) {
return attributes;
}
const layerList = JSON.parse(attributes.layerListJSON);
layerList.forEach((layerDescriptor) => {
if (isEsDocumentSource(layerDescriptor)) {
if (_.has(layerDescriptor, 'sourceDescriptor.topHitsTimeField')) {
layerDescriptor.sourceDescriptor.sortField = layerDescriptor.sourceDescriptor.topHitsTimeField;
layerDescriptor.sourceDescriptor.sortOrder = SORT_ORDER.DESC;
delete layerDescriptor.sourceDescriptor.topHitsTimeField;
}
}
});
return {
...attributes,
layerListJSON: JSON.stringify(layerList),
};
}

View file

@ -0,0 +1,60 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
/* eslint max-len: 0 */
import { topHitsTimeToSort } from './top_hits_time_to_sort';
describe('topHitsTimeToSort', () => {
test('Should handle missing layerListJSON attribute', () => {
const attributes = {
title: 'my map',
};
expect(topHitsTimeToSort({ attributes })).toEqual({
title: 'my map',
});
});
test('Should move topHitsTimeField to sortField for ES documents sources', () => {
const layerListJSON = JSON.stringify([
{
sourceDescriptor: {
type: 'ES_SEARCH',
topHitsSplitField: 'gpsId',
topHitsTimeField: '@timestamp',
}
}
]);
const attributes = {
title: 'my map',
layerListJSON
};
expect(topHitsTimeToSort({ attributes })).toEqual({
title: 'my map',
layerListJSON: '[{\"sourceDescriptor\":{\"type\":\"ES_SEARCH\",\"topHitsSplitField\":\"gpsId\",\"sortField\":\"@timestamp\",\"sortOrder\":\"desc\"}}]',
});
});
test('Should handle ES documents sources without topHitsTimeField', () => {
const layerListJSON = JSON.stringify([
{
sourceDescriptor: {
type: 'ES_SEARCH',
topHitsSplitField: 'gpsId',
}
}
]);
const attributes = {
title: 'my map',
layerListJSON
};
expect(topHitsTimeToSort({ attributes })).toEqual({
title: 'my map',
layerListJSON,
});
});
});

View file

@ -6,6 +6,7 @@
import { extractReferences } from './common/migrations/references';
import { emsRasterTileToEmsVectorTile } from './common/migrations/ems_raster_tile_to_ems_vector_tile';
import { topHitsTimeToSort } from './common/migrations/top_hits_time_to_sort';
export const migrations = {
'map': {
@ -21,6 +22,14 @@ export const migrations = {
'7.4.0': (doc) => {
const attributes = emsRasterTileToEmsVectorTile(doc);
return {
...doc,
attributes,
};
},
'7.5.0': (doc) => {
const attributes = topHitsTimeToSort(doc);
return {
...doc,
attributes,

View file

@ -0,0 +1,292 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`should enable sort order select when sort field provided 1`] = `
<Fragment>
<TooltipSelector
fields={null}
onChange={[Function]}
value={Array []}
/>
<EuiFormRow
describedByIds={Array []}
display="row"
fullWidth={false}
hasEmptyLabelSpace={false}
label="Sort"
labelType="label"
>
<EuiFlexGroup
gutterSize="none"
justifyContent="flexEnd"
>
<EuiFlexItem>
<SingleFieldSelect
compressed={true}
fields={null}
filterField={[Function]}
onChange={[Function]}
placeholder="Select sort field"
value="@timestamp"
/>
</EuiFlexItem>
<EuiFlexItem
grow={false}
>
<EuiSelect
compressed={true}
disabled={false}
fullWidth={false}
hasNoInitialSelection={false}
isLoading={false}
onChange={[Function]}
options={
Array [
Object {
"text": "ASC",
"value": "asc",
},
Object {
"text": "DESC",
"value": "desc",
},
]
}
value="DESC"
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFormRow>
<EuiFormRow
describedByIds={Array []}
display="row"
fullWidth={false}
hasEmptyLabelSpace={false}
labelType="label"
>
<EuiSwitch
checked={false}
label="Show top documents based on sort order"
onChange={[Function]}
/>
</EuiFormRow>
<EuiFormRow
describedByIds={Array []}
display="row"
fullWidth={false}
hasEmptyLabelSpace={false}
labelType="label"
>
<EuiSwitch
checked={true}
label="Dynamically filter for data in the visible map area"
onChange={[Function]}
/>
</EuiFormRow>
</Fragment>
`;
exports[`should render top hits form when useTopHits is true 1`] = `
<Fragment>
<TooltipSelector
fields={null}
onChange={[Function]}
value={Array []}
/>
<EuiFormRow
describedByIds={Array []}
display="row"
fullWidth={false}
hasEmptyLabelSpace={false}
label="Sort"
labelType="label"
>
<EuiFlexGroup
gutterSize="none"
justifyContent="flexEnd"
>
<EuiFlexItem>
<SingleFieldSelect
compressed={true}
fields={null}
filterField={[Function]}
onChange={[Function]}
placeholder="Select sort field"
/>
</EuiFlexItem>
<EuiFlexItem
grow={false}
>
<EuiSelect
compressed={true}
disabled={true}
fullWidth={false}
hasNoInitialSelection={false}
isLoading={false}
onChange={[Function]}
options={
Array [
Object {
"text": "ASC",
"value": "asc",
},
Object {
"text": "DESC",
"value": "desc",
},
]
}
value="DESC"
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFormRow>
<EuiFormRow
describedByIds={Array []}
display="row"
fullWidth={false}
hasEmptyLabelSpace={false}
labelType="label"
>
<EuiSwitch
checked={true}
label="Show top documents based on sort order"
onChange={[Function]}
/>
</EuiFormRow>
<EuiFormRow
describedByIds={Array []}
display="rowCompressed"
fullWidth={false}
hasEmptyLabelSpace={false}
label="Entity"
labelType="label"
>
<SingleFieldSelect
compressed={true}
fields={null}
filterField={[Function]}
onChange={[Function]}
placeholder="Select entity field"
value="trackId"
/>
</EuiFormRow>
<EuiFormRow
describedByIds={Array []}
display="rowCompressed"
fullWidth={false}
hasEmptyLabelSpace={false}
label="Documents per entity"
labelType="label"
>
<ValidatedRange
compressed={true}
data-test-subj="layerPanelTopHitsSize"
max={100}
min={1}
onChange={[Function]}
showInput={true}
showLabels={true}
showRange={true}
step={1}
value={1}
/>
</EuiFormRow>
<EuiFormRow
describedByIds={Array []}
display="row"
fullWidth={false}
hasEmptyLabelSpace={false}
labelType="label"
>
<EuiSwitch
checked={true}
label="Dynamically filter for data in the visible map area"
onChange={[Function]}
/>
</EuiFormRow>
</Fragment>
`;
exports[`should render update source editor 1`] = `
<Fragment>
<TooltipSelector
fields={null}
onChange={[Function]}
value={Array []}
/>
<EuiFormRow
describedByIds={Array []}
display="row"
fullWidth={false}
hasEmptyLabelSpace={false}
label="Sort"
labelType="label"
>
<EuiFlexGroup
gutterSize="none"
justifyContent="flexEnd"
>
<EuiFlexItem>
<SingleFieldSelect
compressed={true}
fields={null}
filterField={[Function]}
onChange={[Function]}
placeholder="Select sort field"
/>
</EuiFlexItem>
<EuiFlexItem
grow={false}
>
<EuiSelect
compressed={true}
disabled={true}
fullWidth={false}
hasNoInitialSelection={false}
isLoading={false}
onChange={[Function]}
options={
Array [
Object {
"text": "ASC",
"value": "asc",
},
Object {
"text": "DESC",
"value": "desc",
},
]
}
value="DESC"
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFormRow>
<EuiFormRow
describedByIds={Array []}
display="row"
fullWidth={false}
hasEmptyLabelSpace={false}
labelType="label"
>
<EuiSwitch
checked={false}
label="Show top documents based on sort order"
onChange={[Function]}
/>
</EuiFormRow>
<EuiFormRow
describedByIds={Array []}
display="row"
fullWidth={false}
hasEmptyLabelSpace={false}
labelType="label"
>
<EuiSwitch
checked={true}
label="Dynamically filter for data in the visible map area"
onChange={[Function]}
/>
</EuiFormRow>
</Fragment>
`;

View file

@ -14,7 +14,7 @@ import { SearchSource } from '../../../kibana_services';
import { hitsToGeoJson } from '../../../elasticsearch_geo_utils';
import { CreateSourceEditor } from './create_source_editor';
import { UpdateSourceEditor } from './update_source_editor';
import { ES_SEARCH, ES_GEO_FIELD_TYPE, ES_SIZE_LIMIT } from '../../../../common/constants';
import { ES_SEARCH, ES_GEO_FIELD_TYPE, ES_SIZE_LIMIT, SORT_ORDER } from '../../../../common/constants';
import { i18n } from '@kbn/i18n';
import { getDataSourceLabel } from '../../../../common/i18n_getters';
import { ESTooltipProperty } from '../../tooltips/es_tooltip_property';
@ -56,9 +56,10 @@ export class ESSearchSource extends AbstractESSource {
geoField: descriptor.geoField,
filterByMapBounds: _.get(descriptor, 'filterByMapBounds', DEFAULT_FILTER_BY_MAP_BOUNDS),
tooltipProperties: _.get(descriptor, 'tooltipProperties', []),
sortField: _.get(descriptor, 'sortField', ''),
sortOrder: _.get(descriptor, 'sortOrder', SORT_ORDER.DESC),
useTopHits: _.get(descriptor, 'useTopHits', false),
topHitsSplitField: descriptor.topHitsSplitField,
topHitsTimeField: descriptor.topHitsTimeField,
topHitsSize: _.get(descriptor, 'topHitsSize', 1),
}, inspectorAdapters);
}
@ -70,9 +71,10 @@ export class ESSearchSource extends AbstractESSource {
onChange={onChange}
filterByMapBounds={this._descriptor.filterByMapBounds}
tooltipProperties={this._descriptor.tooltipProperties}
sortField={this._descriptor.sortField}
sortOrder={this._descriptor.sortOrder}
useTopHits={this._descriptor.useTopHits}
topHitsSplitField={this._descriptor.topHitsSplitField}
topHitsTimeField={this._descriptor.topHitsTimeField}
topHitsSize={this._descriptor.topHitsSize}
/>
);
@ -135,10 +137,24 @@ export class ESSearchSource extends AbstractESSource {
];
}
// Returns sort content for an Elasticsearch search body
_buildEsSort() {
const {
sortField,
sortOrder,
} = this._descriptor;
return [
{
[sortField]: {
order: sortOrder
}
}
];
}
async _getTopHits(layerName, searchFilters, registerCancelCallback) {
const {
topHitsSplitField,
topHitsTimeField,
topHitsSize,
} = this._descriptor;
@ -158,7 +174,7 @@ export class ESSearchSource extends AbstractESSource {
});
const searchSource = await this._makeSearchSource(searchFilters, 0);
searchSource.setField('aggs', {
const aggs = {
entitySplit: {
terms: {
field: topHitsSplitField,
@ -167,13 +183,6 @@ export class ESSearchSource extends AbstractESSource {
aggs: {
entityHits: {
top_hits: {
sort: [
{
[topHitsTimeField]: {
order: 'desc'
}
}
],
_source: {
includes: searchFilters.fieldNames
},
@ -183,7 +192,11 @@ export class ESSearchSource extends AbstractESSource {
}
}
}
});
};
if (this._hasSort()) {
aggs.entitySplit.aggs.entityHits.top_hits.sort = this._buildEsSort();
}
searchSource.setField('aggs', aggs);
const resp = await this._runEsQuery(layerName, searchSource, registerCancelCallback, 'Elasticsearch document top hits request');
@ -193,7 +206,7 @@ export class ESSearchSource extends AbstractESSource {
entityBuckets.forEach(entityBucket => {
const total = _.get(entityBucket, 'entityHits.hits.total', 0);
const hits = _.get(entityBucket, 'entityHits.hits.hits', []);
// Reverse hits list so they are drawn from oldest to newest (per entity) so newest events are on top
// Reverse hits list so top documents by sort are drawn on top
allHits.push(...hits.reverse());
if (total > hits.length) {
hasTrimmedResults = true;
@ -218,10 +231,14 @@ export class ESSearchSource extends AbstractESSource {
// By setting "fields", SearchSource removes all of defaults
searchSource.setField('fields', searchFilters.fieldNames);
if (this._hasSort()) {
searchSource.setField('sort', this._buildEsSort());
}
const resp = await this._runEsQuery(layerName, searchSource, registerCancelCallback, 'Elasticsearch document request');
return {
hits: resp.hits.hits,
hits: resp.hits.hits.reverse(), // Reverse hits so top documents by sort are drawn on top
meta: {
areResultsTrimmed: resp.hits.total > resp.hits.hits.length
}
@ -229,8 +246,13 @@ export class ESSearchSource extends AbstractESSource {
}
_isTopHits() {
const { useTopHits, topHitsSplitField, topHitsTimeField } = this._descriptor;
return !!(useTopHits && topHitsSplitField && topHitsTimeField);
const { useTopHits, topHitsSplitField } = this._descriptor;
return !!(useTopHits && topHitsSplitField);
}
_hasSort() {
const { sortField, sortOrder } = this._descriptor;
return !!sortField && !!sortOrder;
}
async getGeoJsonWithMeta(layerName, searchFilters, registerCancelCallback) {
@ -406,9 +428,10 @@ export class ESSearchSource extends AbstractESSource {
getSyncMeta() {
return {
sortField: this._descriptor.sortField,
sortOrder: this._descriptor.sortOrder,
useTopHits: this._descriptor.useTopHits,
topHitsSplitField: this._descriptor.topHitsSplitField,
topHitsTimeField: this._descriptor.topHitsTimeField,
topHitsSize: this._descriptor.topHitsSize,
};
}

View file

@ -6,7 +6,13 @@
import React, { Fragment, Component } from 'react';
import PropTypes from 'prop-types';
import { EuiFormRow, EuiSwitch } from '@elastic/eui';
import {
EuiFormRow,
EuiSwitch,
EuiFlexGroup,
EuiFlexItem,
EuiSelect,
} from '@elastic/eui';
import { SingleFieldSelect } from '../../../components/single_field_select';
import { TooltipSelector } from '../../../components/tooltip_selector';
@ -14,6 +20,7 @@ import { indexPatternService } from '../../../kibana_services';
import { i18n } from '@kbn/i18n';
import { getTermsFields, getSourceFields } from '../../../index_pattern_util';
import { ValidatedRange } from '../../../components/validated_range';
import { SORT_ORDER } from '../../../../common/constants';
export class UpdateSourceEditor extends Component {
static propTypes = {
@ -21,16 +28,17 @@ export class UpdateSourceEditor extends Component {
onChange: PropTypes.func.isRequired,
filterByMapBounds: PropTypes.bool.isRequired,
tooltipProperties: PropTypes.arrayOf(PropTypes.string).isRequired,
sortField: PropTypes.string,
sortOrder: PropTypes.string.isRequired,
useTopHits: PropTypes.bool.isRequired,
topHitsSplitField: PropTypes.string,
topHitsTimeField: PropTypes.string,
topHitsSize: PropTypes.number.isRequired,
};
state = {
tooltipFields: null,
termFields: null,
dateFields: null,
sortFields: null,
};
componentDidMount() {
@ -64,27 +72,11 @@ export class UpdateSourceEditor extends Component {
return;
}
const dateFields = indexPattern.fields.filter(field => {
return field.type === 'date';
});
this.setState({
dateFields,
tooltipFields: getSourceFields(indexPattern.fields),
termFields: getTermsFields(indexPattern.fields),
sortFields: indexPattern.fields.filter(field => field.sortable),
});
if (!this.props.topHitsTimeField) {
// prefer default time field
if (indexPattern.timeFieldName) {
this.onTopHitsTimeFieldChange(indexPattern.timeFieldName);
} else {
// fall back to first date field in index
if (dateFields.length > 0) {
this.onTopHitsTimeFieldChange(dateFields[0].name);
}
}
}
}
_onTooltipPropertiesChange = propertyNames => {
this.props.onChange({ propName: 'tooltipProperties', value: propertyNames });
@ -102,10 +94,14 @@ export class UpdateSourceEditor extends Component {
this.props.onChange({ propName: 'topHitsSplitField', value: topHitsSplitField });
};
onTopHitsTimeFieldChange = topHitsTimeField => {
this.props.onChange({ propName: 'topHitsTimeField', value: topHitsTimeField });
onSortFieldChange = sortField => {
this.props.onChange({ propName: 'sortField', value: sortField });
};
onSortOrderChange = e => {
this.props.onChange({ propName: 'sortOrder', value: e.target.value });
}
onTopHitsSizeChange = size => {
this.props.onChange({ propName: 'topHitsSize', value: size });
};
@ -115,31 +111,8 @@ export class UpdateSourceEditor extends Component {
return null;
}
let timeFieldSelect;
let sizeSlider;
if (this.props.topHitsSplitField) {
timeFieldSelect = (
<EuiFormRow
label={i18n.translate('xpack.maps.source.esSearch.topHitsTimeFieldLabel', {
defaultMessage: 'Time',
})}
display="rowCompressed"
>
<SingleFieldSelect
placeholder={i18n.translate(
'xpack.maps.source.esSearch.topHitsTimeFieldSelectPlaceholder',
{
defaultMessage: 'Select time field',
}
)}
value={this.props.topHitsTimeField}
onChange={this.onTopHitsTimeFieldChange}
fields={this.state.dateFields}
compressed
/>
</EuiFormRow>
);
sizeSlider = (
<EuiFormRow
label={i18n.translate('xpack.maps.source.esSearch.topHitsSizeLabel', {
@ -185,29 +158,12 @@ export class UpdateSourceEditor extends Component {
/>
</EuiFormRow>
{timeFieldSelect}
{sizeSlider}
</Fragment>
);
}
render() {
let topHitsCheckbox;
if (this.state.dateFields && this.state.dateFields.length) {
topHitsCheckbox = (
<EuiFormRow>
<EuiSwitch
label={i18n.translate('xpack.maps.source.esSearch.useTopHitsLabel', {
defaultMessage: `Show most recent documents by entity`,
})}
checked={this.props.useTopHits}
onChange={this.onUseTopHitsChange}
/>
</EuiFormRow>
);
}
return (
<Fragment>
<TooltipSelector
@ -216,6 +172,56 @@ export class UpdateSourceEditor extends Component {
fields={this.state.tooltipFields}
/>
<EuiFormRow
label={i18n.translate('xpack.maps.source.esSearch.sortLabel', {
defaultMessage: `Sort`,
})}
>
<EuiFlexGroup
gutterSize="none"
justifyContent="flexEnd"
>
<EuiFlexItem>
<SingleFieldSelect
placeholder={i18n.translate(
'xpack.maps.source.esSearch.sortFieldSelectPlaceholder',
{
defaultMessage: 'Select sort field',
}
)}
value={this.props.sortField}
onChange={this.onSortFieldChange}
fields={this.state.sortFields}
compressed
/>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiSelect
disabled={!this.props.sortField}
options={[
{ text: 'ASC', value: SORT_ORDER.ASC },
{ text: 'DESC', value: SORT_ORDER.DESC }
]}
value={this.props.sortOrder}
onChange={this.onSortOrderChange}
compressed
/>
</EuiFlexItem>
</EuiFlexGroup>
</EuiFormRow>
<EuiFormRow>
<EuiSwitch
label={i18n.translate('xpack.maps.source.esSearch.useTopHitsLabel', {
defaultMessage: `Show top documents based on sort order`,
})}
checked={this.props.useTopHits}
onChange={this.onUseTopHitsChange}
/>
</EuiFormRow>
{this.renderTopHitsForm()}
<EuiFormRow>
<EuiSwitch
label={i18n.translate('xpack.maps.source.esSearch.extentFilterLabel', {
@ -226,9 +232,6 @@ export class UpdateSourceEditor extends Component {
/>
</EuiFormRow>
{topHitsCheckbox}
{this.renderTopHitsForm()}
</Fragment>
);
}

View file

@ -0,0 +1,55 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
jest.mock('../../../kibana_services', () => ({}));
import React from 'react';
import { shallow } from 'enzyme';
import { UpdateSourceEditor } from './update_source_editor';
const defaultProps = {
indexPatternId: 'indexPattern1',
onChange: () => {},
filterByMapBounds: true,
tooltipProperties: [],
sortOrder: 'DESC',
useTopHits: false,
topHitsSplitField: 'trackId',
topHitsSize: 1,
};
test('should render update source editor', async () => {
const component = shallow(
<UpdateSourceEditor
{...defaultProps}
/>
);
expect(component).toMatchSnapshot();
});
test('should enable sort order select when sort field provided', async () => {
const component = shallow(
<UpdateSourceEditor
{...defaultProps}
sortField="@timestamp"
/>
);
expect(component).toMatchSnapshot();
});
test('should render top hits form when useTopHits is true', async () => {
const component = shallow(
<UpdateSourceEditor
{...defaultProps}
useTopHits={true}
/>
);
expect(component).toMatchSnapshot();
});

View file

@ -5737,8 +5737,6 @@
"xpack.maps.source.esSearch.topHitsSizeLabel": "エンティティごとのドキュメント数",
"xpack.maps.source.esSearch.topHitsSplitFieldLabel": "エンティティ",
"xpack.maps.source.esSearch.topHitsSplitFieldSelectPlaceholder": "エンティティフィールドを選択",
"xpack.maps.source.esSearch.topHitsTimeFieldLabel": "時間",
"xpack.maps.source.esSearch.topHitsTimeFieldSelectPlaceholder": "タイムフィールドを選択",
"xpack.maps.source.esSearch.useTopHitsLabel": "エンティティによる最も最近のドキュメントを表示",
"xpack.maps.source.esSearchDescription": "Kibana インデックスパターンの地理空間データ",
"xpack.maps.source.esSearchTitle": "ドキュメント",

View file

@ -5740,8 +5740,6 @@
"xpack.maps.source.esSearch.topHitsSizeLabel": "每个实体的文档",
"xpack.maps.source.esSearch.topHitsSplitFieldLabel": "实体",
"xpack.maps.source.esSearch.topHitsSplitFieldSelectPlaceholder": "选择实体字段",
"xpack.maps.source.esSearch.topHitsTimeFieldLabel": "时间",
"xpack.maps.source.esSearch.topHitsTimeFieldSelectPlaceholder": "选择时间字段",
"xpack.maps.source.esSearch.useTopHitsLabel": "按实体显示最近的文档",
"xpack.maps.source.esSearchDescription": "Kibana 索引模式的地理空间数据",
"xpack.maps.source.esSearchTitle": "文档",

View file

@ -42,7 +42,7 @@ export default function ({ getService }) {
type: 'index-pattern'
}
]);
expect(resp.body.migrationVersion).to.eql({ map: '7.4.0' });
expect(resp.body.migrationVersion).to.eql({ map: '7.5.0' });
expect(resp.body.attributes.layerListJSON.includes('indexPatternRefName')).to.be(true);
});
});

View file

@ -105,7 +105,7 @@ export default function ({ getPageObjects, getService }) {
return feature.properties.__kbn__isvisible__;
});
expect(visibilitiesOfFeatures).to.eql([true, true, true, false]);
expect(visibilitiesOfFeatures).to.eql([false, true, true, true]);
});
@ -182,7 +182,7 @@ export default function ({ getPageObjects, getService }) {
return feature.properties.__kbn__isvisible__;
});
expect(visibilitiesOfFeatures).to.eql([false, false, true, false]);
expect(visibilitiesOfFeatures).to.eql([false, true, false, false]);
});