我正在重建一年前建造的东西(不要问旧版本去了哪里——这很尴尬)。
核心功能使用javascript中的$.getJSON
(ajax
-ish)调用,该调用运行一个PHP脚本,该脚本运行一个PostgreSQL查询,该查询构建一个JSON对象并返回它。
问题是,当轮到PostgreSQL大放异彩时,它会吐出什么。
我知道PostgreSQL 9.4+中的build_json_object()
和build_json_array()
功能,但其中一个必须运行该功能的数据库还没有从9.2升级,在接下来的一个月左右我没有时间升级
目前,我正在使用row_to_json()
(以及几何体上的ST_AsGeoJSON()
)来构建我的GeoJSON集合,该集合通过回调返回到客户端。
根据这篇非常好的帖子(并停留在该帖子的查询结构的非常小的ε内),我运行以下查询:
select row_to_json(fc)
from (SELECT 'FeatureCollection' As type,
array_to_json(array_agg(f)) As features
from (SELECT 'Feature' as type,
row_to_json((select l from (select $vars) as l)) as properties,
ST_AsGeoJSON(ST_Transform(lg.g1,4326)) as geometry
from $source_table as lg
where g1 && ST_Transform(ST_SetSRID(ST_MakeEnvelope($bounds),4326),4283)
) as f ) as fc;
($vars
、$source_table
和$bounds
由PHP从POST
变量提供)。
当我查询到$result
和json_encode($result[0]["row_to_json"])
的fetchAll(PDO::FETCH_ASSOC)
时,返回到javascript的对象是一个对象,它可以是JSON.parse()
'd来给出预期的(一个带有FeatureCollection
的Object
,它又包含一堆Feature
s,其中一个是geometry
)。
到目前为止,一切都很好。快速获取数据并在一秒钟左右返回
问题是,在查询阶段,与几何体相关的数组被双引号引用:单个Feature
的JSON的相关段看起来像
{"type":"Feature","geometry":"{''"type''":''"Polygon''",
''"coordinates''":"[[[146.885447408,-36.143199088],
[146.884964384,-36.143136232],
... etc
]]"
}",
"properties":{"address_pfi":"126546461",
"address":"blah blah",
...etc }
}
如果我将PostgreSQL查询结果复制到文件中,就会得到这样的结果:这是在对输出进行任何错误处理之前。
注意只影响几何体{type, coordinates}
的属性(在非JSON意义上)的(双转义)双引号:"几何体"位看起来像
"geometry":"{stuff}"
而不是
"geometry":{stuff}
如果PostgreSQL生成的JSON通过GeoJSONLint的解析器/检查器,它会死在一个尖叫的堆里(它应该死——它绝对不是"spec")——当然它永远不会呈现:正如你所期望的那样,它会吐出"无效类型"。
目前,我已经用一个笨拙的方法(我的正常M.O.)对其进行了分类——当$.getJSON
返回对象时,我
- 把它变成一根绳子,然后
.replace(/"{/g, '{')
和.replace(/}"/g, '}')
和.replace(/''/g, '')
,然后- 把它变成一个物体,然后继续恶作剧
这不是一个好的做法(至少可以说):如果可以鼓励查询本身返回有效的GeoJSON,那会好得多。
很明显,问题出在row_to_json()
阶段:它看到了"几何体"的属性集,并将其与"属性"的属性集合区别对待——它(错误地)用引号转义了"几何"(在斜杠转义所有双引号之后)一个,但(正确地)保留了"属性"一个。
所以在这本书的序言之后。。。问题。
我遗漏或忽略了这个查询的细微差别吗?我有相关PostgreSQL命令的RTFD,除了预通知开关之外,我什么都不知道。
当然,如果有一种节省的方式来完成整个往返行程,我会接受它:唯一需要注意的是,它必须保持其"实时获取"特性——$.getJSON
在谷歌地图中的"空闲"触发器下运行,源表、感兴趣的变量和缩放(决定$bounds
)由用户决定。
(可以认为这是一种通过一次只获取200-300个简单的ish(地籍图)特征来更新地图层的方式,比为10-19的缩放生成整个状态的瓦片金字塔要好得多。我打赌有人已经在bl.ocks上做过这样的事情,但我还没有发现。)。
似乎缺少json的转换。应该是
ST_AsGeoJSON(ST_Transform(lg.g1,4326))::json
如果没有强制转换,st_asgeojson将返回一个经过双重编码的字符串。
然而,您也可以获得属性和geoJson,然后用PHP对json进行json_decode,用PHP创建geoJson featurecollection数组,最后对整个结果进行json_encode。