171 lines
8.1 KiB
Bash
171 lines
8.1 KiB
Bash
#!/bin/bash
|
|
# --------------------------------------------------------------------------
|
|
# overture_ingest.sh — سحب وحقن بيانات Overture (مباني، شوارع، أماكن، حدود)
|
|
#
|
|
# ⚠️ تغيير جوهري عن النسخة القديمة:
|
|
# القديمة كانت تبدأ بـ DROP TABLE overture_place, overture_building,
|
|
# overture_segment — أي أن تشغيلها لأي دولة يمسح بيانات كل الدول الأخرى.
|
|
# الآن الحذف *محصور بالنطاق الجغرافي* الجاري إعادة حقنه فقط، فتبقى بيانات
|
|
# بقية الدول سليمة. هذا يجعل السكربت قابلاً للتشغيل الجزئي وإعادة التشغيل.
|
|
#
|
|
# الاستخدام:
|
|
# bash infrastructure/scripts/overture_ingest.sh # كل النطاقات
|
|
# bash infrastructure/scripts/overture_ingest.sh baghdad # نطاق واحد
|
|
# bash infrastructure/scripts/overture_ingest.sh iraq baghdad # عدة نطاقات
|
|
#
|
|
# ملاحظة عن الأحجام: المباني تُسحب على مستوى المدينة لا الدولة — مباني دولة
|
|
# كاملة قد تتجاوز عدة جيجابايت GeoJSON ولا يحتملها قرص السيرفر الحالي.
|
|
# لذلك: building/segment ← نطاق مدينة، place/division_area ← نطاق دولة.
|
|
# --------------------------------------------------------------------------
|
|
set -euo pipefail
|
|
|
|
APP_DIR="${APP_DIR:-/home/hamzadoctor/app}"
|
|
DB_HOST="${DB_HOST:-localhost}"
|
|
DB_PORT="${DB_PORT:-5432}"
|
|
DB_USER="${DB_USER:-mapuser}"
|
|
DB_NAME="${DB_NAME:-mapdb}"
|
|
DB_PASS="${DB_PASS:-mappass}"
|
|
|
|
cd "$APP_DIR"
|
|
|
|
# ── النطاقات: "minlon,minlat,maxlon,maxlat" ───────────────────────────────
|
|
# نطاقات الدول (للأماكن والحدود الإدارية)
|
|
BBOX_JORDAN_NORTH="35.5,31.7,39.3,33.4"
|
|
BBOX_JORDAN_SOUTH="34.9,29.1,38.0,31.7"
|
|
BBOX_SYRIA="35.7,32.3,42.4,37.3"
|
|
BBOX_EGYPT="24.7,21.9,36.9,31.7"
|
|
BBOX_IRAQ="38.7,29.0,48.8,37.4"
|
|
|
|
# نطاقات المدن (للمباني والشوارع — أثقل بكثير)
|
|
BBOX_AMMAN="35.75,31.75,36.15,32.15"
|
|
BBOX_DAMASCUS="36.15,33.40,36.45,33.62"
|
|
BBOX_CAIRO="31.10,29.85,31.50,30.20"
|
|
# بغداد المركز فقط (~25×17كم). النطاق الأوسع 44.10,33.10,44.70,33.50 تجاوز
|
|
# 632 ألف مبنى وملأ قرص السيرفر قبل أن ينتهي. وسّعه بعد ترقية التخزين.
|
|
BBOX_BAGHDAD="44.28,33.25,44.55,33.40"
|
|
|
|
psql_run() {
|
|
docker compose -f "${APP_DIR}/docker-compose.yml" exec -T db \
|
|
psql -U "$DB_USER" -d "$DB_NAME" "$@"
|
|
}
|
|
|
|
# ── حذف محصور بالنطاق: ينظّف ما سنعيد حقنه فقط، ولا يمس الدول الأخرى ──────
|
|
purge_bbox() {
|
|
local table=$1 bbox=$2
|
|
IFS=',' read -r minx miny maxx maxy <<< "$bbox"
|
|
# to_regclass يمنع الفشل في أول تشغيل قبل أن ينشئ ogr2ogr الجدول
|
|
psql_run -c "
|
|
DO \$\$
|
|
BEGIN
|
|
IF to_regclass('public.${table}') IS NOT NULL THEN
|
|
DELETE FROM ${table}
|
|
WHERE location && ST_MakeEnvelope(${minx}, ${miny}, ${maxx}, ${maxy}, 4326);
|
|
END IF;
|
|
END \$\$;
|
|
"
|
|
}
|
|
|
|
process() {
|
|
local region=$1 bbox=$2 theme=$3
|
|
local output_file="overture_${region}_${theme}.geojson"
|
|
|
|
echo "🌍 [$region] السمة: $theme ..."
|
|
overturemaps download --bbox="$bbox" -f geojson --type="$theme" -o "$output_file"
|
|
|
|
if [ "$theme" == "division_area" ]; then
|
|
echo "📍 الحدود الإدارية جاهزة: $output_file"
|
|
echo " استوردها عبر: POST /geocoding/import-boundaries?country=<CODE>&filePath=/data/${output_file}"
|
|
return
|
|
fi
|
|
|
|
echo "🧹 تنظيف نطاق ${region} من overture_${theme} (بدون المساس بغيره)..."
|
|
purge_bbox "overture_${theme}" "$bbox"
|
|
|
|
echo "🔌 الحقن في PostGIS (overture_${theme})..."
|
|
export PGPASSWORD=$DB_PASS
|
|
# `if !` ضروري: مع set -e يخرج السكربت فوراً عند فشل ogr2ogr فلا يُحذف
|
|
# الملف المؤقت. ملف مباني مدينة كبيرة قد يبلغ عدة جيجابايت، وتَركه بعد
|
|
# فشل سببه امتلاء القرص أصلاً يجعل المحاولة التالية تفشل أسرع.
|
|
if ! ogr2ogr -f "PostgreSQL" \
|
|
PG:"host=$DB_HOST port=$DB_PORT user=$DB_USER dbname=$DB_NAME password=$DB_PASS" \
|
|
"$output_file" \
|
|
-nln "overture_${theme}" \
|
|
-update -append \
|
|
-nlt PROMOTE_TO_MULTI \
|
|
-lco GEOMETRY_NAME=location
|
|
then
|
|
echo "❌ فشل حقن ${region}/${theme} — يُحذف الملف المؤقت ($(du -h "$output_file" 2>/dev/null | cut -f1))"
|
|
rm -f "$output_file"
|
|
return 1
|
|
fi
|
|
|
|
echo "✅ انتهى ${region}/${theme}"
|
|
rm -f "$output_file"
|
|
}
|
|
|
|
# ── تجهيز بيئة بايثون ─────────────────────────────────────────────────────
|
|
if [ ! -d "venv_overture" ]; then
|
|
echo "📦 إنشاء بيئة افتراضية..."
|
|
python3 -m venv venv_overture
|
|
fi
|
|
source venv_overture/bin/activate
|
|
pip install --quiet --upgrade pip
|
|
pip install --quiet overturemaps
|
|
|
|
# ── تعريف النطاقات القابلة للتشغيل ────────────────────────────────────────
|
|
run_jordan() { process jordan_north "$BBOX_JORDAN_NORTH" division_area
|
|
process jordan_north "$BBOX_JORDAN_NORTH" place
|
|
process jordan_south "$BBOX_JORDAN_SOUTH" division_area
|
|
process jordan_south "$BBOX_JORDAN_SOUTH" place; }
|
|
run_syria() { process syria "$BBOX_SYRIA" division_area
|
|
process syria "$BBOX_SYRIA" place; }
|
|
run_egypt() { process egypt "$BBOX_EGYPT" division_area
|
|
process egypt "$BBOX_EGYPT" place; }
|
|
run_iraq() { process iraq "$BBOX_IRAQ" division_area
|
|
process iraq "$BBOX_IRAQ" place; }
|
|
|
|
run_amman() { process amman "$BBOX_AMMAN" building
|
|
process amman "$BBOX_AMMAN" segment; }
|
|
run_damascus() { process damascus "$BBOX_DAMASCUS" building
|
|
process damascus "$BBOX_DAMASCUS" segment; }
|
|
run_cairo() { process cairo "$BBOX_CAIRO" building
|
|
process cairo "$BBOX_CAIRO" segment; }
|
|
run_baghdad() { process baghdad "$BBOX_BAGHDAD" building
|
|
process baghdad "$BBOX_BAGHDAD" segment; }
|
|
|
|
ALL_REGIONS=(jordan syria egypt iraq amman damascus cairo baghdad)
|
|
TARGETS=("$@")
|
|
if [ ${#TARGETS[@]} -eq 0 ]; then
|
|
TARGETS=("${ALL_REGIONS[@]}")
|
|
fi
|
|
|
|
echo "🚀 نطاقات هذا التشغيل: ${TARGETS[*]}"
|
|
for r in "${TARGETS[@]}"; do
|
|
if ! declare -F "run_${r}" >/dev/null; then
|
|
echo "❌ نطاق غير معروف: ${r} — المتاح: ${ALL_REGIONS[*]}"
|
|
exit 2
|
|
fi
|
|
"run_${r}"
|
|
done
|
|
|
|
# ── فهارس مكانية + تسطيح الأسماء (idempotent) ─────────────────────────────
|
|
# name_primary إلزامي: عمود names من نوع json وبلاطات MVT لا تحمل كائنات، فلا
|
|
# يستطيع الستايل قراءة الاسم منه. التفاصيل: infrastructure/sql/09_overture_name_primary.sql
|
|
for t in overture_building overture_segment overture_place; do
|
|
psql_run -c "
|
|
DO \$\$
|
|
BEGIN
|
|
IF to_regclass('public.${t}') IS NOT NULL THEN
|
|
EXECUTE 'CREATE INDEX IF NOT EXISTS idx_${t}_location ON ${t} USING gist (location)';
|
|
EXECUTE 'ALTER TABLE ${t} ADD COLUMN IF NOT EXISTS name_primary text';
|
|
EXECUTE 'UPDATE ${t} SET name_primary = names->>''primary''
|
|
WHERE names IS NOT NULL AND name_primary IS NULL';
|
|
EXECUTE 'CREATE INDEX IF NOT EXISTS idx_${t}_name_primary ON ${t} (name_primary)
|
|
WHERE name_primary IS NOT NULL';
|
|
END IF;
|
|
END \$\$;
|
|
"
|
|
done
|
|
|
|
echo "🎉 اكتمل. البلاطات تُخدم عبر martin تلقائياً (WATCH_DB=true)."
|