[8.6] [maps] Fix uploading FeatureCollection as feature when file contains single Feature (#147207) (#147556)

# Backport

This will backport the following commits from `main` to `8.6`:
- [[maps] Fix uploading FeatureCollection as feature when file contains
single Feature (#147207)](https://github.com/elastic/kibana/pull/147207)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Nathan
Reese","email":"reese.nathan@elastic.co"},"sourceCommit":{"committedDate":"2022-12-14T17:08:00Z","message":"[maps]
Fix uploading FeatureCollection as feature when file contains single
Feature (#147207)\n\nFixes
https://github.com/elastic/kibana/issues/146417\r\n\r\nPR resolves edge
case where when uploading a file containing a\r\nFeatureCollection with
a single feature, the results incorrectly state\r\nthat 2 features where
indexed with one failing.\r\n\r\nCo-authored-by: Kibana Machine
<42973632+kibanamachine@users.noreply.github.com>","sha":"58c11ed59cf73683cd4b3c2bfbfc1623df399705","branchLabelMapping":{"^v8.7.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:fix","Team:Presentation","backport:prev-minor","Feature:Maps","v8.7.0"],"number":147207,"url":"https://github.com/elastic/kibana/pull/147207","mergeCommit":{"message":"[maps]
Fix uploading FeatureCollection as feature when file contains single
Feature (#147207)\n\nFixes
https://github.com/elastic/kibana/issues/146417\r\n\r\nPR resolves edge
case where when uploading a file containing a\r\nFeatureCollection with
a single feature, the results incorrectly state\r\nthat 2 features where
indexed with one failing.\r\n\r\nCo-authored-by: Kibana Machine
<42973632+kibanamachine@users.noreply.github.com>","sha":"58c11ed59cf73683cd4b3c2bfbfc1623df399705"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v8.7.0","labelRegex":"^v8.7.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/147207","number":147207,"mergeCommit":{"message":"[maps]
Fix uploading FeatureCollection as feature when file contains single
Feature (#147207)\n\nFixes
https://github.com/elastic/kibana/issues/146417\r\n\r\nPR resolves edge
case where when uploading a file containing a\r\nFeatureCollection with
a single feature, the results incorrectly state\r\nthat 2 features where
indexed with one failing.\r\n\r\nCo-authored-by: Kibana Machine
<42973632+kibanamachine@users.noreply.github.com>","sha":"58c11ed59cf73683cd4b3c2bfbfc1623df399705"}}]}]
BACKPORT-->

Co-authored-by: Nathan Reese <reese.nathan@elastic.co>
This commit is contained in:
Kibana Machine 2022-12-14 13:11:03 -05:00 committed by GitHub
parent 8079031ff2
commit 1adab28560
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 82 additions and 19 deletions

View file

@ -57,6 +57,7 @@ export class AbstractGeoFileImporter extends Importer implements GeoFileImporter
await this._readUntil(rowLimit, sizeLimit);
return {
features: [...this._features],
invalidFeatures: [...this._invalidFeatures],
previewCoverage: this._hasNext
? Math.round(this._getProgress(this._features.length, this._blockSizeInBytes))
: 100,

View file

@ -68,6 +68,7 @@ describe('previewFile', () => {
previewCoverage: 0,
hasPoints: false,
hasShapes: false,
invalidFeatures: [],
});
});
@ -79,6 +80,67 @@ describe('previewFile', () => {
hasPoints: true,
hasShapes: false,
features: FEATURE_COLLECTION.features,
invalidFeatures: [],
});
});
test('should read single feature from feature collection', async () => {
const file = new File(
[
JSON.stringify({
type: 'FeatureCollection',
features: [
{
type: 'Feature',
properties: {
population: 200,
},
geometry: {
type: 'Point',
coordinates: [-112.0372, 46.608058],
},
},
],
}),
],
'testfile.json',
{ type: 'text/json' }
);
const importer = new GeoJsonImporter(file);
const results = await importer.previewFile();
expect(results.features.length).toBe(1);
expect(results.invalidFeatures.length).toBe(0);
});
test('should read feature when file contains single feature not wrapped in feature collection', async () => {
const fileWithSingleFeature = new File(
[
JSON.stringify({
type: 'Feature',
properties: {
population: 200,
},
geometry: {
type: 'Point',
coordinates: [-112.0372, 46.608058],
},
}),
],
'testfile.json',
{ type: 'text/json' }
);
const importer = new GeoJsonImporter(fileWithSingleFeature);
const results = await importer.previewFile();
expect(results).toEqual({
previewCoverage: 100,
hasPoints: true,
hasShapes: false,
features: FEATURE_COLLECTION.features,
invalidFeatures: [],
});
});
@ -100,6 +162,7 @@ describe('previewFile', () => {
hasPoints: false,
hasShapes: true,
features: [GEOMETRY_COLLECTION_FEATURE],
invalidFeatures: [],
});
});
@ -131,12 +194,11 @@ describe('previewFile', () => {
const importer = new GeoJsonImporter(fileWithFeaturesWithoutGeometry);
const results = await importer.previewFile();
expect(results).toEqual({
previewCoverage: 100,
hasPoints: true,
hasShapes: false,
features: FEATURE_COLLECTION.features,
});
expect(results.previewCoverage).toBe(100);
expect(results.hasPoints).toBe(true);
expect(results.hasShapes).toBe(false);
expect(results.features).toEqual(FEATURE_COLLECTION.features);
expect(results.invalidFeatures.length).toBe(2);
});
test('should read unwrapped feature', async () => {
@ -165,6 +227,7 @@ describe('previewFile', () => {
hasPoints: true,
hasShapes: false,
features: FEATURE_COLLECTION.features,
invalidFeatures: [],
});
});
@ -183,12 +246,10 @@ describe('previewFile', () => {
const importer = new GeoJsonImporter(fileWithNoFeatures);
const results = await importer.previewFile();
expect(results).toEqual({
previewCoverage: 100,
hasPoints: false,
hasShapes: false,
features: [],
});
expect(results.previewCoverage).toBe(100);
expect(results.hasPoints).toBe(false);
expect(results.hasShapes).toBe(false);
expect(results.features).toEqual([]);
});
test('should return empty feature collection if no features with geometry', async () => {
@ -211,11 +272,10 @@ describe('previewFile', () => {
const importer = new GeoJsonImporter(fileWithFeaturesWithNoGeometry);
const results = await importer.previewFile();
expect(results).toEqual({
previewCoverage: 100,
hasPoints: false,
hasShapes: false,
features: [],
});
expect(results.previewCoverage).toBe(100);
expect(results.hasPoints).toBe(false);
expect(results.hasShapes).toBe(false);
expect(results.features).toEqual([]);
expect(results.invalidFeatures.length).toBe(2);
});
});

View file

@ -65,7 +65,7 @@ export class GeoJsonImporter extends AbstractGeoFileImporter {
const isLastBatch = batch.batchType === 'root-object-batch-complete';
if (isLastBatch) {
// Handle single feature geoJson
if (featureIndex === 0) {
if (featureIndex === 0 && features.length === 0) {
if (batch.container) {
features.push(batch.container);
}

View file

@ -9,11 +9,13 @@ import { Feature } from 'geojson';
import { ReactNode } from 'react';
import { ES_FIELD_TYPES } from '@kbn/data-plugin/public';
import { IImporter } from '../types';
import type { ImportFailure } from '../../../common/types';
export interface GeoFilePreview {
features: Feature[];
hasPoints: boolean;
hasShapes: boolean;
invalidFeatures: ImportFailure[];
previewCoverage: number;
}