我目前正在从事一个项目,该项目需要对存储在mySQL数据库中的位置进行地理编码。

我编写了一个小脚本,该脚本将CSV导入mySQL数据库,并自动在每行中用“ 0.000000”填充经度和纬度字段。

现在,我找到了一个脚本,该脚本检查数据库中是否缺少地理编码并进行更新。由于this script已有几年历史,并且刚与Google合作,所以我满足了我的需求(应该与Wordpress和Nominatim一起使用,而不是与Google Maps一起使用)。

导入CSV效果很好,但是运行此脚本更新约5200个位置时,我超时了。不幸的是,我无法增加任何超时设置,因此需要将任务分成多个步骤。

我该怎么做?

在使用PHP时,我还是有点耳熟能详,因此可以提供任何帮助。我已经尝试通过增加一个计数器变量来分割循环,该变量与我需要更新的mySQL行数成平方。现在应该每100行刷新一次页面,但是不幸的是,它实际上并没有工作。它适用于大约500个位置,但之后-超时。

有人知道解决方案吗?

// Opens a connection to a MySQL server
$connection = mysql_connect(DB_HOST, DB_USER, DB_PASSWORD);
if (!$connection) {
die("Not connected : " . mysql_error());
}

// Set the active MySQL database
$db_selected = mysql_select_db(DB_NAME, $connection);
if (!$db_selected) {
die("Can\'t use db : " . mysql_error());
}

// Select all the rows in the markers table
$query = "SELECT * FROM locations WHERE 1";
$result = mysql_query($query);

if (!$result) {
die("Invalid query: " . mysql_error());
}

// Initialize delay in geocode speed
$delay = 0;
function getLnt($address){
    $request_url = "http://nominatim.openstreetmap.org/search?q=".urlencode($address)."&format=json&addressdetails=1";
    $result_string = file_get_contents($request_url);
    $result_json = json_decode($result_string, true);
    return $result_json[0];
}


// Iterate through the rows, geocoding each address


    while ($row = @mysql_fetch_assoc($result)) {

        $geocode_pending = true;

        while ($geocode_pending) {

            $street = $row["address"];
            $zip = $row["zip"];
            $city = $row["city"];
            $id = $row["id"];

            $address = $street.', '.$zip.' '.$city;

            $details = getLnt($address);
            $lat = $details[lat];
            $lng = $details[lon];
            $state = $details[address][state];
            $country_iso = $details[address][country_code];

            if (http_response_code() == 200) {

                // successful geocode
                $geocode_pending = false;

                $query = sprintf("
                    UPDATE locations SET lat = '%s', lng = '%s', state = '%s', country_iso = '%s' WHERE lat = '0.000000' AND lng = '0.000000' AND id = '%s' LIMIT 1;",
                    mysql_real_escape_string($lat), mysql_real_escape_string($lng), mysql_real_escape_string(utf8_decode($state)),mysql_real_escape_string($country_iso),mysql_real_escape_string($id)
                );

                $update_result = mysql_query($query);

                if (!$update_result) {
                   die("Invalid query: " . mysql_error());
                }

        } else if(http_response_code() == 620) {

                // sent geocodes too fast
                $delay += 100000;

            } else if($details == NULL) {

                // failure to geocode
                $geocode_pending = false;
                echo "Address " . $address . " failed to geocoded. ";
                echo "Received status " . $status . "
                \n";

            }
            usleep($delay);

        }

}

最佳答案

您必须在您的位置查询中添加分页:

// Select all the rows in the markers table
$offset = intval($_GET['offset'];
$query = "SELECT * FROM locations WHERE 1 LIMIT $offset, 100";


然后在浏览器中浏览页面。您可以手动执行此操作,也可以在另一页上使用javascript / jquery来查询目标位置:

var locations_count = 1000000;
var offset = 0;
var func = function(){
    $.get('update-location.php', {offset: offset}, function(){
            document.write('<br/>Processed ' + offset + ' records');
            offset += 100;
            if( offset < locations_count )
                setTimeout(func, 100);
            else
                document.write('<br/>Update finished');
    });
};
func();


(不要忘记将locations_count更新为您的实际位置数量)。

等解决方案:

将表转储到本地计算机,然后在本地更新它,然后在服务器上更新结果表。

10-01 05:08
查看更多