@opengis/bi
Version:
BI data visualization module
107 lines (87 loc) • 4.78 kB
JavaScript
import descriptionList from "./descriptionList.js";
import metaFormat from "./metaFormat.js";
async function getDataByLatLng({ pg, layer, table, id, lat, lng, time = [] }) {
// const rclient = getRedis();
// const redisKey = `${pg.options.database}:gis-format:${layer}:${lat}:${lng}`;
// const cacheData = await rclient.get(redisKey);
// if (cacheData && !config.local) return JSON.parse(cacheData);
const { rows: styles = [] } = await pg.query(`select style_id as id, dataset
from gis.style where style_id=any($1::text[])
union all
select dataset_id as id, json_build_array(json_build_object('pk', pk, 'table', table_name, 'query', query, 'card', setting->>'card', 'columns', column_list)) as dataset
from bi.dataset a where dataset_id=any($1::text[])`, [layer.split(',')]);
time.push(Date.now());
if (!styles?.length) {
return { message: `style not found: ${layer}`, status: 400 };
}
const { srids } = await pg.queryCache?.('select json_agg(srid) as srids from spatial_ref_sys').then((res1) => res1.rows?.[0] || {}) || {};
const layers = styles.reduce((acc, curr) => {
curr.dataset?.filter((el) => el.table && (el.pk || pg.pk?.[el.table]))
?.forEach((el) => acc.push({
layer: curr.id,
pk: el.pk || pg.pk?.[el.table],
key: el.key,
table: el.table,
query: el.query,
template: el.card,
column_list: el.column_list,
columns: el.columns || el.column_list?.map((el) => el.name)?.join(','),
srid: el.srid || '4326',
geom: el.geom || 'geom',
step: srids?.includes(el.srid - 0) && el.srid !== '4326' ? 10 : 0.0002,
}));
return acc;
}, [])
.filter((el) => el.pk && el.layer)
.filter((el) => table ? el.table === table : true);
if (!layers.length) {
return { message: 'data not found', status: 404 };
}
const point = `srid=4326;point(${lng} ${lat})`;
// ${el.columns?.split?.filter?.((el) => el) ? `,${el.columns?.split?.filter?.((el) => el) || ''}` : ''}
const q = layers.map((el) => `select ${el.pk}, '${el.layer}' as layer,
row_to_json(t) as data,
st_asgeojson(${el.geom})::json as geom from ${el.table} t
where ${el.query || '1=1'} and ${id ? `${el.pk}::text='${id.replace(/'/g, "''")}'` : '1=1'}
and case
when ST_GeometryType(geom) in ('ST_Polygon','ST_MultiPolygon')
then st_intersects(geom,st_buffer('${point}',${el.step}))
when ST_GeometryType(geom) in ('ST_Line','ST_MultiLineString')
then st_distance(geom,'${point}') < ${el.step}
else false end`).join(' union all ');
// if (config.local && config.debug) console.log(q);
const { rows: objects = [] } = await pg.query(q) || {};
time.push(Date.now());
const rows = objects.map((row) => {
const layerData = layers.find((el) => el.layer === row?.layer) || {};
const rowData = layerData?.columns?.split?.filter?.((el) => el) ? layerData?.columns?.split?.filter?.((el) => el).reduce((acc, curr) => Object.assign(acc, { [curr]: row.data?.[curr] }), {}) : row.data;
return {
...rowData,
...row,
...layerData,
data: undefined,
id: layerData.pk ? row?.[layerData.pk] : undefined,
geom: row.geom,
};
});
const { pk, layer: layerId, card, template } = rows[0] || {};
const dataset = layers.find((el) => el.layer === rows?.[0]?.layer) || {};
const columnList = (dataset.column_list || dataset.columns)?.reduce?.((acc, curr) => Object.assign(acc, { [curr.name]: curr.title || curr.ua || curr.name }), {}) || {};
const columns = card
? Object.keys(card).map(el => `${el}| ${card[el]}`).join('|')
: Object.keys(columnList)?.map((key) => `${columnList[key]}| ${key}`).join('|');
const html = columns && rows?.[0] ? await descriptionList(rows[0], { hash: { columns } }) : undefined;
time.push(Date.now());
await Promise.all(rows.map(async () => {
const layerData = layers.find((el) => el.layer === rows?.[0]?.layer) || {};
const columns = layerData.column_list || layerData.columns;
if (columns?.length && Array.isArray(columns)) {
await metaFormat({ rows, columns });
}
}));
time.push(Date.now());
const resp = { id: rows?.[0]?.[pk], layers: layerId, template, data: rows?.[0], rows, html };
// await rclient.set(redisKey, JSON.stringify(resp), 'EX', 5 * 60);
return resp;
}
export default getDataByLatLng