我正在使用 js/node。按照 You requested too many nodes (limit is 50000) 处的说明进行操作。要么请求更小的区域,要么使用 planet.osm 我已经下载了一个 670MB 的文件,代表一个地理区域中的节点。当我在 vim 中打开它时,它看起来像 xml。
我有兴趣在这个区域内寻找高速公路节点/道路网络。我如何查询这个大文件以获取适当的节点/LineString?
好吧,所以我做了一些假设:
我采取了两种平行的方法:
我不知道这些方法中的任何一种是否是您想要的,但我认为您可以使用代码作为起点!
我创建了一个比你说的稍微大一点的虚拟数据文件,713MB。
这是我写的解析器(在 Node.js 中运行),解析这些数据的技巧是逐行(或以小块)读写,而不是试图将所有数据保存在内存中。 ..
const fs = require('fs');
const readline = require('readline');
parse('./data.xml', './highways.xml', './compact.json');
async function parse(inFile, outFile, jsonFile) {
let startTime = Date.now();
const inStream = fs.createReadStream(inFile);
const outStream = fs.createWriteStream(outFile);
const jsonStream = fs.createWriteStream(jsonFile);
const rl = readline.createInterface({
input: inStream,
crlfDelay: Infinity // consider \r\n to be a single line break
});
// Parse line by line
let inNode = false, nodeMem, firstJsonObj = true;
jsonStream.write('[\n');
for await (const line of rl) {
// look for node spanning several lines
if (line.trim().indexOf('<node ') === 0 && line.trim().slice(-2) !== '/>') {
nodeMem = [];
inNode = true;
}
inNode && nodeMem.push(line);
if (line.trim().indexOf('</node>') === 0) {
inNode = false;
nodeMem = nodeMem.join('\n');
if (nodeMem.includes('k="highway"')) {
outStream.write(nodeMem + '\n');
let j = nodeMem.split('\n')[0];
j = j.slice(j.indexOf('lat'));
j = '{' + j.replaceAll('"', '')
.replaceAll('=', ':').replaceAll('>', '}')
.replace(/(lat|lon)/g, '"$1"')
.replaceAll('"lon":', ', "lon":');
!firstJsonObj && (j = ',\n' + j);
jsonStream.write(' ' + j);
firstJsonObj = false;
}
}
}
// close out streams
outStream.end();
jsonStream.write('\n]');
jsonStream.end();
console.log('Found all those highways and wrote ' +
'a verbose XML file and a compact JSON file.');
console.log(`Time taken ${Date.now() - startTime} ms...`);
}
在我的 Macbook Pro 2021(14" 基本版)上,读取、解析和写入花费了 7151 毫秒。
创建的新的、冗长的 XML 文件,只保留了高速公路节点,大小为 295 MB。
简洁的 JSON 文件大小为 63 MB。
小到足以让我们能够在 Node.js 中将整个 JSON 文件读取到内存中。我用以下代码测试了它:
let startTime = Date.now();
let highways = require('./compact.json');
console.log("Read the json in ", Date.now() - startTime, 'ms');
将所有 JSON 读入内存(作为数据结构)花费了 338 毫秒。
现在你可以用所有这些坐标做任何你想做的事;)进一步过滤它们以进行不同的搜索——通过 REST api 返回它们的一部分。或者也许先将它们写入数据库......
干杯!