Skip to content

Commit 9eda1ed

Browse files
committed
[Maps] Fix document source top hits split by scripted field
1 parent 1ffb171 commit 9eda1ed

File tree

3 files changed

+144
-51
lines changed

3 files changed

+144
-51
lines changed

x-pack/legacy/plugins/maps/public/layers/sources/es_search_source/es_search_source.js

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -241,8 +241,21 @@ export class ESSearchSource extends AbstractESSource {
241241
});
242242
}
243243

244+
_getField(indexPattern, fieldName) {
245+
const field = indexPattern.fields.getByName(fieldName);
246+
if (!field) {
247+
throw new Error(
248+
i18n.translate('xpack.maps.source.esSearch.fieldNotFoundMsg', {
249+
defaultMessage: `Unable to find '{fieldName}'' in index-pattern 'indexPatternTitle'.`,
250+
values: { fieldName, indexPatternTitle: indexPattern.title },
251+
})
252+
);
253+
}
254+
return field;
255+
}
256+
244257
async _getTopHits(layerName, searchFilters, registerCancelCallback) {
245-
const { topHitsSplitField, topHitsSize } = this._descriptor;
258+
const { topHitsSplitField: topHitsSplitFieldName, topHitsSize } = this._descriptor;
246259

247260
const indexPattern = await this.getIndexPattern();
248261
const geoField = await this._getGeoField();
@@ -279,20 +292,31 @@ export class ESSearchSource extends AbstractESSource {
279292
};
280293
}
281294

295+
const cardinalityAgg = { precision_threshold: 1 };
296+
const termsAgg = {
297+
size: DEFAULT_MAX_BUCKETS_LIMIT,
298+
shard_size: DEFAULT_MAX_BUCKETS_LIMIT,
299+
};
300+
const topHitsSplitField = this._getField(indexPattern, topHitsSplitFieldName);
301+
if (topHitsSplitField.scripted) {
302+
const script = {
303+
source: topHitsSplitField.script,
304+
lang: topHitsSplitField.lang,
305+
};
306+
cardinalityAgg.script = script;
307+
termsAgg.script = script;
308+
} else {
309+
cardinalityAgg.field = topHitsSplitFieldName;
310+
termsAgg.field = topHitsSplitFieldName;
311+
}
312+
282313
const searchSource = await this._makeSearchSource(searchFilters, 0);
283314
searchSource.setField('aggs', {
284315
totalEntities: {
285-
cardinality: {
286-
field: topHitsSplitField,
287-
precision_threshold: 1,
288-
},
316+
cardinality: cardinalityAgg,
289317
},
290318
entitySplit: {
291-
terms: {
292-
field: topHitsSplitField,
293-
size: DEFAULT_MAX_BUCKETS_LIMIT,
294-
shard_size: DEFAULT_MAX_BUCKETS_LIMIT,
295-
},
319+
terms: termsAgg,
296320
aggs: {
297321
entityHits: {
298322
top_hits: topHits,

x-pack/test/functional/apps/maps/documents_source/top_hits.js

Lines changed: 54 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -13,60 +13,73 @@ export default function({ getPageObjects, getService }) {
1313
const inspector = getService('inspector');
1414
const find = getService('find');
1515

16-
describe('top hits', () => {
17-
before(async () => {
18-
await PageObjects.maps.loadSavedMap('document example top hits');
19-
});
20-
21-
it('should not fetch any search hits', async () => {
22-
await inspector.open();
23-
await inspector.openInspectorRequestsView();
24-
const requestStats = await inspector.getTableData();
25-
const hits = PageObjects.maps.getInspectorStatRowHit(requestStats, 'Hits');
26-
expect(hits).to.equal('0'); // aggregation requests do not return any documents
27-
});
28-
29-
it('should display top hits per entity', async () => {
30-
const mapboxStyle = await PageObjects.maps.getMapboxStyle();
31-
expect(mapboxStyle.sources[VECTOR_SOURCE_ID].data.features.length).to.equal(10);
32-
});
33-
34-
describe('configuration', () => {
16+
describe('geo top hits', () => {
17+
describe('split on string field', () => {
3518
before(async () => {
36-
await PageObjects.maps.openLayerPanel('logstash');
37-
// Can not use testSubjects because data-test-subj is placed range input and number input
38-
const sizeInput = await find.byCssSelector(
39-
`input[data-test-subj="layerPanelTopHitsSize"][type='number']`
40-
);
41-
await sizeInput.click();
42-
await sizeInput.clearValue();
43-
await sizeInput.type('3');
44-
await PageObjects.maps.waitForLayersToLoad();
19+
await PageObjects.maps.loadSavedMap('document example top hits');
4520
});
4621

47-
after(async () => {
48-
await PageObjects.maps.closeLayerPanel();
22+
it('should not fetch any search hits', async () => {
23+
await inspector.open();
24+
await inspector.openInspectorRequestsView();
25+
const requestStats = await inspector.getTableData();
26+
const hits = PageObjects.maps.getInspectorStatRowHit(requestStats, 'Hits');
27+
expect(hits).to.equal('0'); // aggregation requests do not return any documents
4928
});
5029

51-
it('should update top hits when configation changes', async () => {
30+
it('should display top hits per entity', async () => {
5231
const mapboxStyle = await PageObjects.maps.getMapboxStyle();
53-
expect(mapboxStyle.sources[VECTOR_SOURCE_ID].data.features.length).to.equal(15);
32+
expect(mapboxStyle.sources[VECTOR_SOURCE_ID].data.features.length).to.equal(10);
5433
});
55-
});
5634

57-
describe('query', () => {
58-
before(async () => {
59-
await PageObjects.maps.setAndSubmitQuery('machine.os.raw : "win 8"');
35+
describe('configuration', () => {
36+
before(async () => {
37+
await PageObjects.maps.openLayerPanel('logstash');
38+
// Can not use testSubjects because data-test-subj is placed range input and number input
39+
const sizeInput = await find.byCssSelector(
40+
`input[data-test-subj="layerPanelTopHitsSize"][type='number']`
41+
);
42+
await sizeInput.click();
43+
await sizeInput.clearValue();
44+
await sizeInput.type('3');
45+
await PageObjects.maps.waitForLayersToLoad();
46+
});
47+
48+
after(async () => {
49+
await PageObjects.maps.closeLayerPanel();
50+
});
51+
52+
it('should update top hits when configation changes', async () => {
53+
const mapboxStyle = await PageObjects.maps.getMapboxStyle();
54+
expect(mapboxStyle.sources[VECTOR_SOURCE_ID].data.features.length).to.equal(15);
55+
});
56+
});
57+
58+
describe('query', () => {
59+
before(async () => {
60+
await PageObjects.maps.setAndSubmitQuery('machine.os.raw : "win 8"');
61+
});
62+
63+
after(async () => {
64+
await PageObjects.maps.setAndSubmitQuery('');
65+
});
66+
67+
it('should apply query to top hits request', async () => {
68+
await PageObjects.maps.setAndSubmitQuery('machine.os.raw : "win 8"');
69+
const mapboxStyle = await PageObjects.maps.getMapboxStyle();
70+
expect(mapboxStyle.sources[VECTOR_SOURCE_ID].data.features.length).to.equal(2);
71+
});
6072
});
73+
});
6174

62-
after(async () => {
63-
await PageObjects.maps.setAndSubmitQuery('');
75+
describe('split on scripted field', () => {
76+
before(async () => {
77+
await PageObjects.maps.loadSavedMap('document example top hits split with scripted field');
6478
});
6579

66-
it('should apply query to top hits request', async () => {
67-
await PageObjects.maps.setAndSubmitQuery('machine.os.raw : "win 8"');
80+
it('should display top hits per entity', async () => {
6881
const mapboxStyle = await PageObjects.maps.getMapboxStyle();
69-
expect(mapboxStyle.sources[VECTOR_SOURCE_ID].data.features.length).to.equal(2);
82+
expect(mapboxStyle.sources[VECTOR_SOURCE_ID].data.features.length).to.equal(24);
7083
});
7184
});
7285
});

x-pack/test/functional/es_archives/maps/kibana/data.json

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,62 @@
278278
}
279279
}
280280

281+
{
282+
"type": "doc",
283+
"value": {
284+
"id": "map:4ea1e4f0-4dba-11ea-b554-4ba0def79f86",
285+
"index": ".kibana",
286+
"source": {
287+
"map": {
288+
"title" : "document example top hits split with scripted field",
289+
"description" : "",
290+
"mapStateJSON" : "{\"zoom\":4.1,\"center\":{\"lon\":-100.61091,\"lat\":33.23887},\"timeFilters\":{\"from\":\"2015-09-20T00:00:00.000Z\",\"to\":\"2015-09-24T01:00:00.000Z\"},\"refreshConfig\":{\"isPaused\":true,\"interval\":1000},\"query\":{\"query\":\"\",\"language\":\"kuery\"},\"filters\":[]}",
291+
"layerListJSON" : "[{\"id\":\"0hmz5\",\"sourceDescriptor\":{\"type\":\"EMS_TMS\",\"id\":\"road_map\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"TILE\",\"properties\":{}},\"type\":\"VECTOR_TILE\",\"minZoom\":0,\"maxZoom\":24},{\"id\":\"z52lq\",\"label\":\"logstash\",\"minZoom\":0,\"maxZoom\":24,\"sourceDescriptor\":{\"id\":\"e1a5e1a6-676c-4a89-8ea9-0d91d64b73c6\",\"type\":\"ES_SEARCH\",\"geoField\":\"geo.coordinates\",\"limit\":2048,\"filterByMapBounds\":true,\"showTooltip\":true,\"tooltipProperties\":[],\"useTopHits\":true,\"topHitsSplitField\":\"hour_of_day\",\"topHitsSize\":1,\"sortField\":\"@timestamp\",\"sortOrder\":\"desc\",\"applyGlobalQuery\":true,\"indexPatternRefName\":\"layer_1_source_index_pattern\"},\"visible\":true,\"temporary\":false,\"style\":{\"type\":\"VECTOR\",\"properties\":{\"fillColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#e6194b\"}},\"lineColor\":{\"type\":\"STATIC\",\"options\":{\"color\":\"#FFFFFF\"}},\"lineWidth\":{\"type\":\"STATIC\",\"options\":{\"size\":1}},\"iconSize\":{\"type\":\"STATIC\",\"options\":{\"size\":10}},\"symbolizeAs\":{\"options\":{\"value\":\"circle\"}},\"icon\":{\"type\":\"STATIC\",\"options\":{\"value\":\"airfield\"}}},\"previousStyle\":null},\"type\":\"VECTOR\"}]",
292+
"uiStateJSON" : "{\"isLayerTOCOpen\":true,\"openTOCDetails\":[]}",
293+
"bounds" : {
294+
"type" : "Polygon",
295+
"coordinates" : [
296+
[
297+
[
298+
-141.61334,
299+
47.30762
300+
],
301+
[
302+
-141.61334,
303+
16.49119
304+
],
305+
[
306+
-59.60848,
307+
16.49119
308+
],
309+
[
310+
-59.60848,
311+
47.30762
312+
],
313+
[
314+
-141.61334,
315+
47.30762
316+
]
317+
]
318+
]
319+
}
320+
},
321+
"type" : "map",
322+
"references" : [
323+
{
324+
"name" : "layer_1_source_index_pattern",
325+
"type" : "index-pattern",
326+
"id" : "c698b940-e149-11e8-a35a-370a8516603a"
327+
}
328+
],
329+
"migrationVersion" : {
330+
"map" : "7.7.0"
331+
},
332+
"updated_at" : "2020-02-12T17:08:36.671Z"
333+
}
334+
}
335+
}
336+
281337
{
282338
"type": "doc",
283339
"value": {

0 commit comments

Comments
 (0)