🕵️ HackingReopening im Loft: Was ist neu da oben? - Wien - Kurier(17.09.2026 um 05:14 Uhr)
🕵️ HackingTangerhütte: Hacker greifen Verwaltung an - radio SAW(17.09.2026 um 06:32 Uhr)
🕵️ HackingReopening im Loft: Was ist neu da oben? - Wien - Kurier(17.09.2026 um 05:14 Uhr)
🕵️ HackingTangerhütte: Hacker greifen Verwaltung an - radio SAW(17.09.2026 um 06:32 Uhr)
🔧 Programmierung 🕛 vor 7 Monaten 5 Min Lesezeit
0

Geolocalização Performática com Postgres e PostGIS: Uma abordagem prática no projeto Photofy

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht

Desenvolvendo o Photofy aqui em Paulista, percebi que a busca tradicional por "cidade" era muito frustrante. Um fotógrafo que mora no Janga está colado em Olinda, mas se o cliente buscasse apenas por profissionais em "Recife", o sistema simplesmente ignorava quem estava a poucos quarteirões de distância por causa de um limite invisível no banco de dados. Percebi que a geolocalização não é apenas um recurso estético; é o que faz o contrato ser viável ou não, reduzindo o custo de deslocamento para o fotógrafo e trazendo resultados reais para o cliente.






O Problema da Fronteira Invisível



O erro comum é achar que a geografia respeita o texto. Buscar por city: "Recife" é frágil porque o banco não sabe que Olinda é vizinha de Recife.



Minha primeira ideia foi a mais óbvia (o famoso Naive Approach): puxar todos os usuários do banco para o Node.js e rodar a fórmula de Haversine na mão. Mas logo vi o problema: se o Photofy crescer para 10 ou 20 mil fotógrafos, eu ia sobrecarregar a memória do servidor processando um array gigante a cada busca. A saída mais inteligente foi usar o PostGIS, deixando essa matemática pesada para a engine do PostgreSQL, que já é otimizada para isso.






Por que PostGIS? (Teoria Rápida)



Para o projeto funcionar, precisei decidir entre dois tipos de dados espaciais:




  • Geometry: Trata a Terra como um plano cartesiano.

  • Geography: Trata a Terra como um esferoide (curvo).



Escolhi o tipo Geography com o padrão SRID 4326 (WGS 84) — o mesmo usado pelo GPS dos smartphones. Isso me permitiu trabalhar com distâncias em metros de forma nativa.



Para a performance, implementei o índice GiST (Generalized Search Tree). Diferente do B-Tree comum, o GiST trabalha com "Bounding Boxes" (caixas delimitadoras). Na prática, o banco descarta instantaneamente áreas enormes (como ignorar todo o estado da Paraíba) antes mesmo de começar a filtrar os fotógrafos disponíveis em Pernambuco.






Mão na Massa: Configurando o Banco



Na hora de codar com NestJS e Prisma, a realidade foi um pouco mais desafiadora. Como o Prisma ainda é limitado com tipos espaciais nativos, o "pulo do gato" foi usar o tipo Unsupported no schema e editar a migration manualmente.






1. O Schema (prisma.schema)






CODE
model User {
// ... outros campos

// O tipo Unsupported força o Prisma a ignorar a validação JS
// mas cria a coluna correta no banco
location Unsupported("geography(Point, 4326)")?

// Índice GiST é OBRIGATÓRIO para performance
@@index([location], name: "location_idx", type: Gist)
}









2. A Migration SQL



O Prisma gera o arquivo SQL, mas precisei adicionar manualmente o comando para habilitar a extensão no topo:




CODE
-- Habilitar a extensão ANTES de criar a tabela
CREATE EXTENSION IF NOT EXISTS postgis;

-- Alterar a tabela (gerado pelo Prisma)
ALTER TABLE "users" ADD COLUMN "location" geography(Point, 4326);









Integrando ao Backend (NestJS)



Com o banco pronto, conectei o backend via Raw Queries ($queryRaw) para garantir que o índice GiST fosse realmente utilizado. Para converter endereço em coordenada (Geocoding), usei a API do Nominatim.






1. O Serviço de Geocoding (Simplificado)






CODE
// backend/src/utils/geocoding.service.ts
async getCoordinates(address: string) {
const params = new URLSearchParams({ q: address, format: 'json', limit: '1' });

// O header User-Agent é obrigatório para a API do Nominatim
const response = await fetch(`https://nominatim.openstreetmap.org/search?${params}`, {
headers: { 'User-Agent': 'Photofy-Project' },
});

const data = await response.json();
return data[0] ? { lat: parseFloat(data[0].lat), lng: parseFloat(data[0].lon) } : null;
}









2. A Busca Espacial (O Pulo do Gato)



Aqui usamos o Raw Query para acessar as funções ST_DWithin (filtro de raio usando índice) e ST_Distance (calculo exato de metros).




CODE
// backend/src/users/users.service.ts

// Interface essencial para o TypeScript entender o retorno do banco
interface UserWithDistance {
id: string;
distance: number;
}

async findNearbyPhotographers(lat: number, lng: number, radiusKm: number) {
// ST_SetSRID cria um ponto GPS válido (WGS 84)
const result = await this.prisma.$queryRaw<UserWithDistance[]>`
SELECT
id, name,
ST_Distance(
location,
ST_SetSRID(ST_MakePoint(
${lng}, ${lat}), 4326)::geography
) as distance
FROM users
WHERE
ST_DWithin(
location,
ST_SetSRID(ST_MakePoint(
${lng}, ${lat}), 4326)::geography,
${radiusKm * 1000}
)
ORDER BY distance ASC
`
;

return result;
}









Conclusão: O Banco não é apenas um Depósito de Dados



Essa jornada no Photofy me tirou da zona de conforto do "Code First" e me fez entender que o banco de dados não é apenas um depósito de dados, mas uma engine de computação poderosa.



Delegar a lógica espacial para o PostGIS limpou meu código e protegeu o Event Loop do Node.js. Hoje, o sistema está pronto para escalar para milhares de usuários com custo computacional $O(\log N)$, conectando pessoas em Paulista, Olinda e Recife com base na distância real e não em simples comparações de texto.






Referências



NESTJS. Documentation: A progressive Node.js framework. 2024. Disponível em: . Acesso em: 11 fev. 2026.



POSTGIS PROJECT. PostGIS 3.4.0 Manual. 2023. Disponível em: . Acesso em: 11 fev. 2026.



PRISMA DATA, INC. Prisma Documentation: Working with MongoDB, PostgreSQL, and more. 2024. Disponível em: https://www.prisma.io/docs. Acesso em: 11 fev. 2026.

Vollständiger Original-Artikel
Den kompletten Beitrag mit allen Details direkt auf dev.to lesen.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
1 Quelle
Built a PPL-aware ALPC enumerator because standard handle duplication was leaving blind spots in the attack surface
1 Quelle
SindriKit V2.0.0 (C framework to decouple technique logic from execution mechanics)
1 Quelle
Heap-Buffer-Überlauf im Discord-Backend
Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten Geolocalização Performática com Postgres e PostGIS: Uma abordagem prática no projeto Photofy

Thematisch verwandte Begriffe: Geolocalização, Performática, Postgres, PostGIS · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...