MENA region data enrichment scripts` -> Wait, let's keep it concise and clean.
* *Option 3:* `feat: add tourist landmarks support with UI sheets, data models
This commit is contained in:
@@ -0,0 +1,149 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const { Client } = require(path.join(__dirname, '../../apps/api/node_modules/pg'));
|
||||
|
||||
const dataPath = path.join(__dirname, '../../apps/web/public/data/landmarks_mena_expanded.json');
|
||||
const landmarks = JSON.parse(fs.readFileSync(dataPath, 'utf8'));
|
||||
const allLandmarks = landmarks;
|
||||
|
||||
console.log(`Found ${allLandmarks.length} MENA regional landmarks to ingest.`);
|
||||
|
||||
const client = new Client({
|
||||
host: '188.68.36.205',
|
||||
port: 5432,
|
||||
user: 'mapuser',
|
||||
password: 'mappass',
|
||||
database: 'mapdb'
|
||||
});
|
||||
|
||||
async function main() {
|
||||
await client.connect();
|
||||
console.log('Connected to PostgreSQL mapdb on 188.68.36.205');
|
||||
|
||||
await client.query(`CREATE SCHEMA IF NOT EXISTS heritage;`);
|
||||
await client.query(`
|
||||
CREATE TABLE IF NOT EXISTS heritage.landmarks (
|
||||
id SERIAL PRIMARY KEY,
|
||||
slug VARCHAR(100) UNIQUE NOT NULL,
|
||||
name_ar VARCHAR(255) NOT NULL,
|
||||
name_en VARCHAR(255),
|
||||
category VARCHAR(100) NOT NULL,
|
||||
era VARCHAR(100),
|
||||
narrative_ar TEXT,
|
||||
narrative_en TEXT,
|
||||
audio_url VARCHAR(500),
|
||||
image_url VARCHAR(500),
|
||||
centroid_geom geometry(Point, 4326) NOT NULL,
|
||||
access_gate_geom geometry(Point, 4326),
|
||||
parking_geom geometry(Point, 4326),
|
||||
ticket_office_geom geometry(Point, 4326),
|
||||
governorate VARCHAR(100),
|
||||
is_verified BOOLEAN DEFAULT true,
|
||||
metadata JSONB DEFAULT '{}'::jsonb,
|
||||
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
|
||||
);
|
||||
CREATE INDEX IF NOT EXISTS idx_heritage_landmarks_centroid ON heritage.landmarks USING GIST(centroid_geom);
|
||||
`);
|
||||
|
||||
let insertedCount = 0;
|
||||
let updatedCount = 0;
|
||||
|
||||
for (const l of allLandmarks) {
|
||||
const slug = l.slug || `lm-${l.id}`;
|
||||
const nameAr = l.name_ar || l.name;
|
||||
const nameEn = l.name_en || null;
|
||||
const category = l.category || 'heritage_site';
|
||||
const era = l.era || null;
|
||||
const narrativeAr = l.narrative_ar || l.narrative || null;
|
||||
const narrativeEn = l.narrative_en || null;
|
||||
const audioUrl = l.audio_url || null;
|
||||
const imageUrl = l.image_url || l.image || null;
|
||||
const governorate = l.governorate || null;
|
||||
const isVerified = l.is_verified ?? true;
|
||||
|
||||
const cLng = l.coordinates?.centroid?.lng ?? l.centroid?.lng ?? l.lng ?? (Array.isArray(l.coordinates) ? l.coordinates[0] : null);
|
||||
const cLat = l.coordinates?.centroid?.lat ?? l.centroid?.lat ?? l.lat ?? (Array.isArray(l.coordinates) ? l.coordinates[1] : null);
|
||||
|
||||
const gLng = l.coordinates?.access_gate?.lng ?? l.gate?.lng ?? null;
|
||||
const gLat = l.coordinates?.access_gate?.lat ?? l.gate?.lat ?? null;
|
||||
|
||||
const pLng = l.coordinates?.parking?.lng ?? l.parking?.lng ?? null;
|
||||
const pLat = l.coordinates?.parking?.lat ?? l.parking?.lat ?? null;
|
||||
|
||||
const tLng = l.coordinates?.ticket_office?.lng ?? l.ticket?.lng ?? null;
|
||||
const tLat = l.coordinates?.ticket_office?.lat ?? l.ticket?.lat ?? null;
|
||||
|
||||
const metaObj = {
|
||||
...(l.metadata || {}),
|
||||
country: l.country,
|
||||
curator: l.curator || l.metadata?.curator || 'وزارة السياحة والآثار',
|
||||
tier: l.tier,
|
||||
admission: l.admission,
|
||||
site_polygon: l.site_polygon,
|
||||
trail_name: l.trail_name || l.metadata?.trail_name,
|
||||
turathi_trail_id: l.turathi_trail_id || l.metadata?.turathi_trail_id,
|
||||
turathi_stop_id: l.turathi_stop_id || l.metadata?.turathi_stop_id,
|
||||
turathi_trail_name: l.turathi_trail_name || l.metadata?.turathi_trail_name,
|
||||
has_visitor_center: l.has_visitor_center || l.metadata?.has_visitor_center
|
||||
};
|
||||
|
||||
const query = `
|
||||
INSERT INTO heritage.landmarks (
|
||||
slug, name_ar, name_en, category, era, narrative_ar, narrative_en,
|
||||
audio_url, image_url, centroid_geom, access_gate_geom, parking_geom,
|
||||
ticket_office_geom, governorate, is_verified, metadata, updated_at
|
||||
) VALUES (
|
||||
$1, $2, $3, $4, $5, $6, $7,
|
||||
$8, $9,
|
||||
ST_SetSRID(ST_Point($10, $11), 4326),
|
||||
CASE WHEN $12::float IS NOT NULL AND $13::float IS NOT NULL THEN ST_SetSRID(ST_Point($12, $13), 4326) ELSE NULL END,
|
||||
CASE WHEN $14::float IS NOT NULL AND $15::float IS NOT NULL THEN ST_SetSRID(ST_Point($14, $15), 4326) ELSE NULL END,
|
||||
CASE WHEN $16::float IS NOT NULL AND $17::float IS NOT NULL THEN ST_SetSRID(ST_Point($16, $17), 4326) ELSE NULL END,
|
||||
$18, $19, $20::jsonb, CURRENT_TIMESTAMP
|
||||
)
|
||||
ON CONFLICT (slug) DO UPDATE SET
|
||||
name_ar = EXCLUDED.name_ar,
|
||||
name_en = EXCLUDED.name_en,
|
||||
category = EXCLUDED.category,
|
||||
era = EXCLUDED.era,
|
||||
narrative_ar = EXCLUDED.narrative_ar,
|
||||
narrative_en = EXCLUDED.narrative_en,
|
||||
audio_url = EXCLUDED.audio_url,
|
||||
image_url = EXCLUDED.image_url,
|
||||
centroid_geom = EXCLUDED.centroid_geom,
|
||||
access_gate_geom = EXCLUDED.access_gate_geom,
|
||||
parking_geom = EXCLUDED.parking_geom,
|
||||
ticket_office_geom = EXCLUDED.ticket_office_geom,
|
||||
governorate = EXCLUDED.governorate,
|
||||
is_verified = EXCLUDED.is_verified,
|
||||
metadata = EXCLUDED.metadata,
|
||||
updated_at = CURRENT_TIMESTAMP;
|
||||
`;
|
||||
|
||||
const values = [
|
||||
slug, nameAr, nameEn, category, era, narrativeAr, narrativeEn,
|
||||
audioUrl, imageUrl,
|
||||
cLng, cLat,
|
||||
gLng, gLat,
|
||||
pLng, pLat,
|
||||
tLng, tLat,
|
||||
governorate, isVerified, JSON.stringify(metaObj)
|
||||
];
|
||||
|
||||
await client.query(query, values);
|
||||
insertedCount++;
|
||||
}
|
||||
|
||||
const finalCount = await client.query('SELECT count(*) as count FROM heritage.landmarks');
|
||||
console.log(`\n🎉 Ingestion successful!`);
|
||||
console.log(`Processed: ${insertedCount} landmarks`);
|
||||
console.log(`Total heritage.landmarks in DB: ${finalCount.rows[0].count}`);
|
||||
|
||||
await client.end();
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error('Ingestion error:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user