Я пытаюсь добавить данные lat и long для адресации записей в нашей базе данных, чтобы мы могли предоставить локатор магазина как страницу. Я использую эта страница в качестве руководства. Я пытаюсь создать CSV-файл геокодированных адресов с идентификаторами для импорта в нашу базу данных. В конце концов я хочу автоматизировать это, но сейчас я делаю это вручную для начальной загрузки.
У нас более 3000 записей в нашей базе данных, и я продолжаю выходить за пределы запросов с помощью API геокодирования. Я добавил задержку для каждого запроса, как предложено для нескольких вопросов здесь. К сожалению, большинство из этих ответов до того, как Google изменил структуру цен и квоту на свои API. Кажется, что после 1000 или около того я продолжаю бояться API OVER QUERY LIMIT
ошибка. Некоторые вызовы работают после того, как я получаю сообщение об ошибке, но чем дольше я выполняю код, тем меньше отношение успешности к ошибке.
Документация Google гласит, что QPS для геокодирования составляет 50, но я обнаружил проблемы при выполнении более 10. Поэтому я добавил задержку в 1500 мс для разметки своих запросов, но она, похоже, не работает. Оплата премиум-плана не является вариантом, так как мы должны делать это каждые 30 дней, в соответствии с политикой хранения данных Google. Я делаю это на стороне клиента, так как на нашем сервере нет настроек java, node, pip или go.
Редактировать: я сделал еще несколько поисков и обернул свое геокодирование в функцию, и если это не удалось, рекурсивно вызвать его снова после задержки. Но страница продолжает падать, как только я получаю, я начинаю получать ошибки сверх лимита. Чего я не понимаю, так это того, почему он выдает сотни таких ошибок, причем больше, чем количество адресов для анализа, если я возвращаю ошибочные вызовы в setTimeout
функция.
Edit2: Хорошо, я все ближе. Я заставил свою функцию геокодирования возвращать обещание и объявил его вне основного кода. Упаковка setTimeout
над разделом, который goecodes распределял их соответственно. Я установил перехват для устранения ошибки и повторите попытку. Теперь моя проблема в том, что мой Promise.all()
решается, даже если некоторые из обещаний не выполнены и все еще находятся в процессе повторной попытки. Я не хочу, чтобы это закончилось, пока не будут выполнены невыполненные обещания.
Мой код выглядит следующим образом:
db.php
<?php
$mysqli = new mysqli("host", "user", "pass", "table");
$addresses = array();
if ($mysqli->connect_errno) {
echo "Failed to connect to MySQL: (" . $mysqli->connect_errno . ") " . $mysqli->connect_error;
}
$query = "SELECT
id,
Concat(
primary_address_street, ' ', primary_address_city,
' ', primary_address_state, ' ',
primary_address_postalcode
) as address
FROM
`nurses`
WHERE
primary_address_postalcode <> ''
AND primary_address_street <> ''
AND primary_address_city <> ''
AND primary_address_state <> ''
AND first_name <> ''
AND last_name <> ''
";
$i = 0;
//Used multi_query because I originally did multiple queries
if ($mysqli->multi_query($query)) {
do {
if ($result = $mysqli->store_result()) {
while ($row = $result->fetch_row()) {
$addresses[$i] = array('id' => $row[0], 'address' => $row[1]);
$i++;
}
$result->free();
}
} while ($mysqli->next_result());
}
echo json_encode($addresses);
map.js
var map;
var nurses = [];
function initMap() {
map = new google.maps.Map(document.getElementById('map'), {
center: { lat: myLat, lng: myLng },
zoom: 15,
// disableDefaultUI: true,
// gestureHandling: 'none',
// zoomControl: false
});
var bounds = new google.maps.LatLngBounds();
var geocoder = new google.maps.Geocoder();
var oReq = new XMLHttpRequest();
oReq.onload = function() {
// console.log(this.responseText);
var dbAdresses = JSON.parse(this.responseText);
// console.log(dbAdresses);
var locationPromises = [];
dbAdresses.forEach(function(e, i) {
locationPromises.push(geocodeAddress(e, i));
});
Promise.all(locationPromises)
.then(function(locationsFound) {
// console.log(locationsFound);
// console.log(nurses);
const replacer = (key, value) => value === null ? '' : value;
const header = Object.keys(nurses[0]);
let csv = nurses.map(row => header.map(fieldName => JSON.stringify(row[fieldName], replacer)).join(','));
csv.unshift(header.join(','));
csv = csv.join('\r\n');
//Download the file as CSV
var downloadLink = document.createElement("a");
var blob = new Blob(["\ufeff", csv]);
var url = URL.createObjectURL(blob);
downloadLink.href = url;
downloadLink.download = "nurses-addresses.csv";
document.body.appendChild(downloadLink);
downloadLink.click();
document.body.removeChild(downloadLink);
})
.catch(function(e) { console.log(e); });
};
oReq.open("get", "db_csv.php", true);
oReq.send();
}
function geocodeAddress(entry, index) {
var geocoder = new google.maps.Geocoder();
return new Promise(function(resolve, reject) {
setTimeout(function() {
geocoder.geocode({
'address': JSON.stringify(entry.address)
}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
console.log(results);
var person = {
'id': entry.id,
'lat': results[0].geometry.location.lat(),
'lng': results[0].geometry.location.lng()
};
nurses.push(person);
resolve(results);
} else {
console.log("Geocode was not successful for the following reason: " + status);
reject(status);
}
});
}, 1000 * index);
})
.catch(function() {
console.log(entry.id + " failed retrying in 5 seconds");
setTimeout(function() {
geocodeAddress(entry, index);
}, 5000);
});
}
Задача ещё не решена.
Других решений пока нет …