/
origins.js
105 lines (90 loc) · 3.11 KB
/
origins.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
'use strict';
import centerOfMass from '@turf/center-of-mass';
import db from '../../db/';
import { getPropInsensitive } from '../../utils/utils';
import {
getJSONFileContents
} from '../../s3/utils';
import { downloadWbCatalogProjectFile } from '../../utils/wbcatalog';
/**
* Processes the Origins depending on the source.
*
* Origins
* Catalog:
* - Download from server
* - Cleanup and store in DB
* File:
* - Cleanup and store in DB
*
* @param {number} projId Project id
* @param {object} options Additional parameters
* @param {object} options.op Operation instance
* @param {object} options.logger Output logger
*/
export default async function (projId, {op, logger}) {
logger && logger.log('process origins');
await op.log('process:origins', {message: 'Processing origins'});
const source = await db('projects_source_data')
.select('*')
.where('project_id', projId)
.where('name', 'origins')
.first();
let originsData;
if (source.type === 'wbcatalog') {
originsData = await downloadWbCatalogProjectFile(projId, source, logger);
}
if (source.type === 'file') {
originsData = await db('projects_files')
.select('*')
.where('project_id', projId)
.where('type', 'origins')
.first();
}
// Clean the tables so any remnants of previous attempts are removed.
// This avoids primary keys collisions.
await db('projects_origins')
.where('project_id', projId)
.del();
const indicators = originsData.data.indicators;
const neededProps = indicators.map(o => o.key);
const originsFC = await getJSONFileContents(originsData.path);
logger && logger.log('origins before filter', originsFC.features.length);
const features = originsFC.features.filter(feat => {
const props = Object.keys(feat.properties);
return neededProps.every(o => props.indexOf(o) !== -1);
});
logger && logger.log('origins after filter', features.length);
const originsIndicators = [];
const origins = features.map(feat => {
const coordinates = feat.geometry.type === 'Point'
? feat.geometry.coordinates
: centerOfMass(feat).geometry.coordinates;
// Will be flattened later.
// The array is constructed in this way so we can match the index of the
// results array and attribute the correct id.
const featureIndicators = indicators.map(ind => ({
key: ind.key,
label: ind.label,
value: parseInt(feat.properties[ind.key])
}));
originsIndicators.push(featureIndicators);
return {
project_id: projId,
name: feat.properties[getPropInsensitive(feat.properties, 'name')] || 'N/A',
coordinates: JSON.stringify(coordinates)
};
});
await db.transaction(async function (trx) {
const ids = await trx.batchInsert('projects_origins', origins)
.returning('id');
// Add ids to the originsIndicators and flatten the array in the process.
let flat = [];
originsIndicators.forEach((resInd, resIdx) => {
resInd.forEach(ind => {
ind.origin_id = ids[resIdx];
flat.push(ind);
});
});
await trx.batchInsert('projects_origins_indicators', flat);
});
}