diff --git a/src/libs/routes/api.js b/src/libs/routes/api.js index 43424f24e46b3b8679ff82d7719981953a34d883..75ef583f3aee59d414f9535b4261fcd9edf1c7c6 100644 --- a/src/libs/routes/api.js +++ b/src/libs/routes/api.js @@ -63,7 +63,6 @@ api.use('/state', state); api.use('/region', region); api.use('/city', city); api.use('/school', school); -// api.use('/spatial', spatial); api.use('/classroom', classroom); api.use('/teacher', teacher); api.use('/idhmr', idhmr); diff --git a/src/libs/routes/spatial.js b/src/libs/routes/spatial.js deleted file mode 100644 index 93dd1d37aebc9877594285c538c179ae93394313..0000000000000000000000000000000000000000 --- a/src/libs/routes/spatial.js +++ /dev/null @@ -1,355 +0,0 @@ -const express = require('express'); - -const libs = `${process.cwd()}/libs`; - -const squel = require('squel'); - -const log = require(`${libs}/log`)(module); - -const query = require(`${libs}/middlewares/query`); - -const sqlQuery = require(`${libs}/db/query_exec`); - -const response = require(`${libs}/middlewares/response`); - -const ReqQueryFields = require(`${libs}/middlewares/reqQueryFields`); - -const id2str = require(`${libs}/middlewares/id2str`); - -const spatialApp = express(); - -let rqf = new ReqQueryFields(); - -function processResultSet(querySet, querySetLabels = ["result"], singleResult = false) { - const resultMap = new Map(); - let resultIdx = 0; - // loop relies on the fact that Promise.all maintains the order of the original iterable - for(let result of querySet) { - const resultLbl = querySetLabels[resultIdx]; - resultMap[resultLbl] = []; - if (singleResult) { - resultMap[resultLbl] = result[0]; - } else { - for(let row of result) { - log.debug(row); - resultMap[resultLbl].push(row); - } - } - resultIdx++; - } - log.debug(resultMap); - return resultMap; -} - -function dbExecAll(querySet = []) { - // Issue all queries concurrently to the database, for every query object in the iterable - // NOTE: Array.map() returns a copy of the original array with each object 'mapped'. - return querySet.map((qry) => { return sqlQuery(qry.toString()); }); -} - -rqf.addField({ - name: 'filter', - field: true, - where: true -}).addValue({ - name: 'region', - table: 'regiao', - tableField: 'nome', - resultField: 'region_name', - where: { - relation: '=', - type: 'integer', - field: 'id' - }, - join: { - primary: 'id', - foreign: 'regiao_id' - } -}).addValue({ - name: 'state', - table: 'estado', - tableField: 'nome', - resultField: 'state_name', - where: { - relation: '=', - type: 'integer', - field: 'id' - }, - join: { - primary: 'id', - foreign: 'estado_id' - } -}).addValue({ - name: 'city', - table: 'municipio', - tableField: 'nome', - resultField: 'city_name', - where: { - relation: '=', - type: 'integer', - field: 'id' - }, - join: { - primary: 'id', - foreign: 'municipio_id' - } -}).addValue({ - name: 'school', - table: 'escola', - tableField: 'nome_escola', - resultField: 'school_name', - where: { - relation: '=', - type: 'integer', - field: 'id' - } -}); - -spatialApp.get('/sociodemographic', rqf.parse(), rqf.build(), (req, res, next) => { - const populationYearQry = squel.select() - .field('MAX(ibge_populacao.ano_censo)') - .from('ibge_populacao'); - - const populationQry = req.sql.clone() - .field('\'Brasil\'', 'name') - .field('SUM(populacao)', 'population') - .field('ibge_populacao.ano_censo', 'census_year') - .from('ibge_populacao') - .where(`ibge_populacao.ano_censo IN (${populationYearQry.toString()})`) - .group('ibge_populacao.ano_censo'); - - const pibYearQry = squel.select() - .field('MAX(ibge_pib.ano_censo)') - .from('ibge_pib'); - - const pibQry = req.sql.clone() - .field('\'Brasil\'', 'name') - .field('AVG(ibge_pib.pib_per_capita)', 'gdp_per_capita') - .field('ibge_pib.ano_censo', 'census_year') - .from('ibge_pib') - .where(`ibge_pib.ano_censo IN (${pibYearQry.toString()})`) - .group('ibge_pib.ano_censo'); - - const idhYearQry = squel.select() - .field('MAX(adh_idh.ano_censo)') - .from('adh_idh'); - - const idhQry = req.sql.clone() - .field('\'Brasil\'', 'name') - .field('AVG(idhm)', 'idhm') - .field('adh_idh.ano_censo', 'census_year') - .from('adh_idh') - .where(`adh_idh.ano_censo IN (${idhYearQry.toString()})`) - .group('adh_idh.ano_censo'); - - const analfabYearQry = squel.select() - .field('MAX(adh_analfabetismo.ano_censo)') - .from('adh_analfabetismo'); - - const analfabQry = req.sql.clone() - .field('\'Brasil\'', 'name') - .field('AVG(t_analf15m)', 'analfabetism') - .field('adh_analfabetismo.ano_censo', 'census_year') - .from('adh_analfabetismo') - .where(`adh_analfabetismo.ano_censo IN (${analfabYearQry.toString()})`) - .group('adh_analfabetismo.ano_censo'); - - const giniYearQry = squel.select() - .field('MAX(adh_gini.ano_censo)') - .from('adh_gini'); - - const giniQry = req.sql.clone() - .field('\'Brasil\'', 'name') - .field('AVG(gini)', 'gini') - .field('adh_gini.ano_censo', 'census_year') - .from('adh_gini') - .where(`adh_gini.ano_censo IN (${giniYearQry.toString()})`) - .group('adh_gini.ano_censo'); - - // map query objects to their respective response labels - const queryLabels = [ "population", "gdp", "idh", "analfab", "gini" ]; - const querySet = [ populationQry, pibQry, idhQry, analfabQry, giniQry ]; - // wait until all queries finish or one of them fail - Promise.all(dbExecAll(querySet)).then((queryResults) => { - req.result = processResultSet(queryResults, queryLabels, true); - next(); - }).catch((error) => { - log.error(`[SQL query error] ${error}`); - next(error); - }); -}, response('spatial')); - -spatialApp.get('/educational', rqf.parse(), rqf.build(), (req, res, next) => { - const censusYearQry = squel.select() - .field('MAX(escola.ano_censo)', 'ano_censo') - .from('escola') - .toString(); - - const totalSchoolsQry = req.sql.clone() - .field('\'Brasil\'', 'name') - .field('\'Total\'', 'location_name') - .field('COUNT(DISTINCT(escola.id))', 'total') - .field('escola.ano_censo', 'census_year') - .from('turma') - .from('escola') - .where('escola.ano_censo=turma.ano_censo AND escola.id=turma.escola_id') - .where(`escola.ano_censo IN (${censusYearQry})`) - .where('turma.tipo_turma_id = 0') - .group('escola.ano_censo'); - - const schoolsPerLocationQry = req.sql.clone() - .field('\'Brasil\'', 'name') - .field('COUNT(DISTINCT(escola.id))', 'total') - .field('escola.ano_censo', 'census_year') - .field('localizacao.descricao', 'location_name') - .from('localizacao') - .from('turma') - .from('escola') - .where('escola.cod_localizacao=localizacao.id') - .where('escola.ano_censo=turma.ano_censo AND escola.id=turma.escola_id') - .where(`escola.ano_censo IN (${censusYearQry})`) - .where('turma.tipo_turma_id = 0') - .group('escola.cod_localizacao') - .group('escola.ano_censo') - .group('localizacao.descricao') - .order('localizacao.descricao'); - - const schoolsPerAdmDependencyQry = req.sql.clone() - .field('\'Brasil\'', 'name') - .field('COUNT(DISTINCT(escola.id))', 'total') - .field('escola.ano_censo', 'census_year') - .field('dependencia_adm.nome', 'adm_dependency_name') - .from('dependencia_adm') - .from('escola') - .where('escola.dependencia_adm_id=dependencia_adm.id') - .where(`escola.ano_censo IN (${censusYearQry})`) - .group('escola.ano_censo') - .group('dependencia_adm.nome') - .order('escola.ano_censo') - .order('dependencia_adm.nome'); - - const enrollmentsQry = req.sql.clone() - .field('\'Brasil\'', 'name') - .field('COALESCE(SUM(uc201.matriculas), 0)', 'total') - .field('uc201.ano_censo', 'census_year') - .from('uc201') - .group('uc201.ano_censo'); - - const enrollmentsPerAdmDepQry = req.sql.clone() - .field('\'Brasil\'', 'name') - .field('COALESCE(SUM(uc201.matriculas), 0)', 'total') - .field('uc201.ano_censo', 'census_year') - .field('dependencia_adm.nome', 'adm_dependency_name') - .from('dependencia_adm') - .from('uc201') - .where('uc201.dependencia_adm_id=dependencia_adm.id') - .group('dependencia_adm.nome') - .group('uc201.ano_censo'); - - const enrollmentsPerSchoolLevelQry = req.sql.clone() - .field('\'Brasil\'', 'name') - .field('COALESCE(SUM(uc201.matriculas), 0)', 'total') - .field('uc201.ano_censo', 'census_year') - .field('etapa_ensino.desc_etapa', 'school_level_name') - .field('dependencia_adm.nome', 'adm_dependency_name') - .from('etapa_ensino') - .from('dependencia_adm') - .from('uc201') - .where('uc201.etapas_mod_ensino_segmento_id=etapa_ensino.id') - .where('uc201.dependencia_adm_id=dependencia_adm.id') - .group('etapa_ensino.desc_etapa') - .group('dependencia_adm.nome') - .group('uc201.ano_censo'); - - const enrollmentsPerLocationQry = req.sql.clone() - .field('\'Brasil\'', 'name') - .field('COALESCE(SUM(uc201.matriculas), 0)', 'total') - .field('uc201.ano_censo', 'census_year') - .field('localizacao.descricao', 'location_name') - .from('localizacao') - .from('uc201') - .where('uc201.localizacao=localizacao.id') - .group('localizacao.descricao') - .group('uc201.ano_censo'); - - const queryLabels = [ "school", "school_per_location", "school_per_adm_dependency", "enrollment", "enrollment_per_adm_dep", - "enrollment_per_school_level", "enrollment_per_location" ]; - const querySet = [ totalSchoolsQry, schoolsPerLocationQry, schoolsPerAdmDependencyQry, enrollmentsQry, - enrollmentsPerAdmDepQry, enrollmentsPerSchoolLevelQry, enrollmentsPerLocationQry]; - // wait until all queries finish or one of them fail - Promise.all(dbExecAll(querySet)).then((queryResults) => { - req.result = processResultSet(queryResults, queryLabels); - next(); - }).catch((error) => { - log.error(`[SQL query error] ${error}`); - next(error); - }); -}, response('spatial')); - -spatialApp.get('/educational/school_level', rqf.parse(), rqf.build(), (req, res, next) => { - const enrollmentsPerSchoolLevelYearQry = squel.select() - .field('MAX(matricula.ano_censo)', 'census_year') - .from('matricula'); - - const enrollmentsPerSchoolLevelQry = req.sql.clone() - .field('COALESCE(COUNT(matricula.id), 0)', 'total') - .field('matricula.ano_censo', 'census_year') - .field('matricula.serie_ano_id', 'school_year') - .field('etapa_ensino.desc_etapa', 'school_level') - .from('etapa_ensino') - .from('matricula') - .where(`matricula.ano_censo IN (${enrollmentsPerSchoolLevelYearQry.toString()})`) - .where('matricula.etapa_ensino_id = etapa_ensino.id') - .where('matricula.tipo <= 3') - .group('etapa_ensino.desc_etapa') - .group('etapa_ensino.id') - .group('matricula.serie_ano_id') - .group('matricula.ano_censo') - .order('etapa_ensino.id') - .order('matricula.serie_ano_id') - .order('matricula.ano_censo'); - - const queryLabels = [ 'enrollment_per_school_level', 'enrollment_census_year' ]; - const querySet = [ enrollmentsPerSchoolLevelQry, enrollmentsPerSchoolLevelYearQry ]; - // wait until all queries finish or one of them fail - Promise.all(dbExecAll(querySet, enrollmentsPerSchoolLevelYearQry)).then((queryResults) => { - const result = queryResults[0]; - const censusYear = queryResults[1][0]['census_year']; - - let school_levels = {}; - for(let i = 0; i < result.length; ++i) { - const school_year = id2str.schoolYear(result[i].school_year); - const school_level = result[i].school_level; - const census_year = result[i].census_year; - if (typeof school_levels[school_level] === 'undefined') { - school_levels[school_level] = {}; - } - school_levels[school_level][school_year] = parseInt(result[i].total, 10); - } - - let response = []; - for(let level in school_levels) { - if (school_levels.hasOwnProperty(level)) { - let sclevel = {}; - sclevel["degree"] = level; - sclevel["census_year"] = parseInt(censusYear, 10); - sclevel["table"] = []; - for(let school_year in school_levels[level]) { - if (school_levels[level].hasOwnProperty(school_year)) { - let enrollment = { 'title' : school_year, - 'value' : school_levels[level][school_year] }; - sclevel["table"].push(enrollment); - } - } - response.push(sclevel); - } - } - req.result = response; - next(); - }).catch((error) => { - log.error(`[SQL query error] ${error}`); - next(error); - }); -}, response('spatial')); - -module.exports = spatialApp;