【问题标题】:How extract jsonb column in fields by key如何按键提取字段中的jsonb列
【发布时间】:2020-04-09 22:48:21
【问题描述】:

我正在使用 postgresql 和 postgis 插件。

我已经用这个方案存储了数据:table_id is primary key, properties is a jsonb and geom as geometry(GeometryZ,4326);

如果我提出这个请求:select table_id, properties, geom from nametable 返回所有信息,其中 table_id 为整数,属性为 jsonb,geom 为几何(GeometryZ,4326)。

我想要一个属性返回 table_id 的查询,一个列的列表,其中列的名称是 value 的键,他的 value 和 geom。例如,如果属性具有名称和密度,则返回如下响应:table_id | name | density | geom |,但我不知道属性的名称,所以我认为应该是该查询中的查询,获取键的名称。

我最近得到它,它的查询是:select jsonb_object_keys(properties) as key from nametable;

谢谢

编辑:

首先,我在我的 postgressql 数据库中存储了一个 jsonb 字段,所以我想将该 jsonb 提取到列中。但已将包含不同属性的不同表存储到 jsonb 列中。

所以,我们的想法是获取一个查询,其中选择 table_id、属性(在多个列中提取)和 geom。

1 - 有了这个我有键的名称:select jsonb_object_keys(properties) as key from nametable group by key;

2 - 使用键获取每个键的所有值。

3 - 返回一个查询,当我调用它时,返回 table_id、从 jsonb 中提取的属性列、从 nametable 中提取的 geom;

我的问题是我不知道如何使用子查询生成该查询。

【问题讨论】:

  • 您能否提供 1 一些示例数据 2) 正是您期望的输出结果和 3) 告诉我们您的查询出了什么问题。
  • 好的,我将编辑问题以便更好地解释我的情况
  • 样本数据最好显示为formatted text。请参阅here,了解有关如何创建漂亮表格的一些提示。

标签: sql postgresql postgis


【解决方案1】:

您是否尝试过使用CTE

WITH j AS (
  SELECT 
    table_id, 
    properties->>'name' AS name,
    properties->>'density' AS density,
    geom 
  FROM t)
SELECT * FROM j WHERE j.name = 'Alabama'; 

【讨论】:

  • 很好,但我不知道 jsonb 列的键.. 在这种情况下是名称和密度,但在其他情况下将是不同的键.. 所以我想动态地获取键并进行查询当你发帖时
【解决方案2】:

感谢所有帮助我的人。

这里是用于查询的代码以与磁贴服务器一起使用。

我使用这个查询来获取一个键数组:

const sql = SELECT ARRAY_AGG(f) as keys FROM (SELECT jsonb_object_keys(properties) f FROM ${options.layerName} group by f) u;

然后,创建一个查询以将每个属性获取为名为@9​​87654322@ 的列的函数,

/** CONSTANTS **/
const TILE_SIZE = 256;
const PROJECTION_STRING = '+init=epsg:3857';

/** LIBRARIES **/
var zlib = require('zlib');
var express = require('express');
var mapnik = require('mapnik');
var Promise = require('promise');
var SphericalMercator = require('sphericalmercator');

const { pool } = require('../postgressql/config');

var mercator = new SphericalMercator({
    size: TILE_SIZE
});

mapnik.register_default_input_plugins();

var app = express();

app.get('/:namelayer/:z/:x/:y.pbf', (req, res, next) => {
    var options = {
        x: parseInt(req.params.x),
        y: parseInt(req.params.y),
        z: parseInt(req.params.z),
        layerName: req.params.namelayer
    };

   const sql = `SELECT ARRAY_AGG(f) as keys FROM (SELECT jsonb_object_keys(properties) f FROM ${options.layerName} group by f) u`;
    try {
        pool.query(sql, (error, results) => {
            if (error) {
                return res.status(500).json({
                    ok: false,
                    message: error
                });
            }

            const keys = (results && results.rows && results.rows.length > 0 && results.rows[0].keys && results.rows[0].keys.length >0) ? results.rows[0].keys.slice() : [];
            const sql = generateSQL(options, keys);

            makeVectorTile(options, sql).then( (vectorTile) => {
                zlib.deflate(vectorTile, (err, data) => {
                    if (err) {
                        return res.status(500).send(err.message);
                    }

                    res.setHeader('Content-Encoding', 'deflate');
                    res.setHeader('Content-Type', 'application/x-protobuf');
                    res.setHeader('Access-Control-Allow-Origin', '*');
                    return res.send(data);
                });
            });
        });
    } catch (e) {
        res.status(404).send({
            error: e.toString(),
        });
    }
});

function generateSQL(options, keys) {

    if (keys.length === 0) {
        return `select table_id, geom from ${options.layerName}`;
    } else {
        let sql = "";
        keys.forEach( key => {
            sql = sql + `(properties->>'${key}') as ${key},`;
        });
        sql = `select table_id, ${sql} geom from ${options.layerName}`
        return sql;
    }
};

function makeVectorTile(options, sql) {

    var extent = mercator.bbox(options.x, options.y, options.z, false, '3857');
    var map = new mapnik.Map(TILE_SIZE, TILE_SIZE, PROJECTION_STRING);
    map.extent = extent;

    var layer = new mapnik.Layer(options.layerName);
    layer.datasource = new mapnik.Datasource({
        type: process.env.DB_TYPE,
        dbname: process.env.DB_DATABASE,
        // table: options.layerName,
        table: `(${sql}) as tile`,
        user: process.env.DB_USER,
        password: process.env.DB_PASSWORD
    });

    layer.styles = ['default'];
    map.add_layer(layer);

    return new Promise( (resolve, reject) => {
        var vtile = new mapnik.VectorTile(parseInt(options.z), parseInt(options.x), parseInt(options.y));
        map.render(vtile, function (err, vtile) {
            if (err) {
                return reject(err);
            }
            console.log(`${vtile.getData().length} KB`);
            resolve(vtile.getData());
        });
    });
};

module.exports = app;

【讨论】:

    猜你喜欢
    • 2019-11-20
    • 1970-01-01
    • 2017-06-23
    • 2015-07-16
    • 2021-02-24
    • 2021-07-08
    • 2020-11-18
    • 2022-10-19
    相关资源
    最近更新 更多