2026-04-14-1

This commit is contained in:
Hamza-Ayed
2026-04-14 03:03:35 +03:00
parent b36e197e09
commit 581eda1ea8
15 changed files with 102069 additions and 304 deletions
+24 -51
View File
@@ -69,6 +69,7 @@ export class GeocodingService {
const userQuery = `
SELECT
p.id, p.name, p.name_ar, p.name_en, p.category,
p.neighborhood_id as db_neighborhood_id,
p.neighbourhood as original_neighbourhood,
n.name_ar as neighbourhood,
d.name_ar as district,
@@ -77,9 +78,9 @@ export class GeocodingService {
CASE WHEN $2::float IS NOT NULL THEN ST_DistanceSphere(p.location, ST_SetSRID(ST_MakePoint($3::float, $2::float), 4326)) ELSE 0 END as distance,
similarity(COALESCE(p.name_ar, ''), $1) + similarity(COALESCE(p.name, ''), $1) + similarity(COALESCE(p.neighbourhood, ''), $1) as relevance
FROM ${tableName} p
LEFT JOIN admin_boundaries n ON p.admin_level10_id = n.id
LEFT JOIN admin_boundaries d ON p.admin_level8_id = d.id
LEFT JOIN admin_boundaries g ON p.admin_level4_id = g.id
LEFT JOIN neighborhood_polygons n ON p.neighborhood_id = n.id
LEFT JOIN admin_boundaries d ON p.sub_district_id = d.id
LEFT JOIN admin_boundaries g ON p.governorate_id = g.id
WHERE (p.name_ar % $1 OR p.name % $1 OR p.neighbourhood % $1 OR p.name_ar ILIKE $4 OR p.name ILIKE $4 OR p.neighbourhood ILIKE $4)
${hasLocation ? `AND (p.location && ST_Expand(ST_SetSRID(ST_MakePoint($3::float, $2::float), 4326), $5::float) OR ST_DistanceSphere(p.location, ST_SetSRID(ST_MakePoint($3::float, $2::float), 4326)) <= $6::float)` : ''}
ORDER BY relevance DESC, distance ASC LIMIT 15
@@ -107,55 +108,27 @@ export class GeocodingService {
const osmResults = await this.osmPointsRepository.query(osmQuery, [cleanQuery, lat || null, lon || null, ILikeQuery, radiusInDegrees, radius]);
allResults.push(...osmResults);
// --- Consolidation: Overture Maps Integration (Now in primary DB) ---
const overtureQuery = `
(SELECT id::text,
COALESCE(names->>'primary', names->>'common', 'Building') as name,
COALESCE(names->>'primary', names->>'common', '') as name_ar,
NULL as name_en,
'building' as category,
ST_Y(ST_Centroid(location)) as latitude,
ST_X(ST_Centroid(location)) as longitude,
'' as address,
'overture_buildings' as source,
CASE WHEN $2::float IS NOT NULL THEN ST_DistanceSphere(location, ST_SetSRID(ST_MakePoint($3::float, $2::float), 4326)) ELSE 0 END as distance,
0.6 as relevance
FROM overture_building
WHERE (names->>'primary' ILIKE $4 OR names->>'common' ILIKE $4)
LIMIT 15)
UNION ALL
(SELECT id::text,
COALESCE(names->>'primary', names->>'common', 'Street') as name,
COALESCE(names->>'primary', names->>'common', '') as name_ar,
NULL as name_en,
'transportation' as category,
ST_Y(ST_Centroid(location)) as latitude,
ST_X(ST_Centroid(location)) as longitude,
'' as address,
'overture_streets' as source,
CASE WHEN $2::float IS NOT NULL THEN ST_DistanceSphere(location, ST_SetSRID(ST_MakePoint($3::float, $2::float), 4326)) ELSE 0 END as distance,
0.6 as relevance
FROM overture_segment
WHERE (names->>'primary' ILIKE $4 OR names->>'common' ILIKE $4)
LIMIT 15)
`;
try {
const overtureResults = await this.osmPointsRepository.query(overtureQuery, [cleanQuery, lat || null, lon || null, ILikeQuery]);
allResults.push(...overtureResults);
} catch (err) {
this.logger.warn('Overture tables search failed, logging error.', err);
}
// Note: We removed the raw query to 'overture_building' because raw overture tables
// do not have administrative linking, causing empty full_addresses, and
// scanning them with ILIKE without trigram indices causes a 2-second latency spike.
// Overture data is already properly ingested via the Scraper into places_jordan.
const sortedResults = allResults
.sort((a, b) => hasLocation ? ((a.distance - b.distance) || (b.relevance - a.relevance)) : ((b.relevance - a.relevance) || (a.distance - b.distance)))
.slice(0, 25)
.map(r => ({
...r,
latitude: parseFloat(r.latitude),
longitude: parseFloat(r.longitude),
distance_km: r.distance ? (Number(r.distance) / 1000).toFixed(2) : null,
location: { lat: parseFloat(r.latitude), lng: parseFloat(r.longitude) },
}));
.map(r => {
// Build full administrative address from admin_boundaries
const addressParts = [r.neighbourhood, r.district, r.governorate].filter(Boolean);
const full_address = addressParts.length > 0 ? addressParts.join('، ') : (r.address || '');
return {
...r,
latitude: parseFloat(r.latitude),
longitude: parseFloat(r.longitude),
distance_km: r.distance ? (Number(r.distance) / 1000).toFixed(2) : null,
location: { lat: parseFloat(r.latitude), lng: parseFloat(r.longitude) },
full_address,
};
});
return { results: sortedResults };
} catch (e) {
@@ -177,9 +150,9 @@ export class GeocodingService {
p.latitude, p.longitude, p.address, 'user_place' as source,
ST_DistanceSphere(p.location::geometry, ST_SetSRID(ST_MakePoint($1::float, $2::float), 4326)) as distance
FROM ${tableName} p
LEFT JOIN admin_boundaries n ON p.admin_level10_id = n.id
LEFT JOIN admin_boundaries d ON p.admin_level8_id = d.id
LEFT JOIN admin_boundaries g ON p.admin_level4_id = g.id
LEFT JOIN neighborhood_polygons n ON p.neighborhood_id = n.id
LEFT JOIN admin_boundaries d ON p.sub_district_id = d.id
LEFT JOIN admin_boundaries g ON p.governorate_id = g.id
WHERE p.location IS NOT NULL
ORDER BY p.location::geometry <-> ST_SetSRID(ST_MakePoint($1::float, $2::float), 4326) ASC LIMIT 3
`;