28

我正在使用 Google Places API 使用 javascript 自动完成地址

当我在输入框中输入地址的单元号和街道号时,它会在建议下拉列表中显示结果,但是当我选择地址时,操作“place_changed”事件的侦听器没有任何地址与地址组件类型为“子前提” ' 甚至 formatted_address 属性中也没有单位编号。尽管它确实包含来自 'street number'、'city'、'country' 等的其他详细信息

例如:如果我输入“1403/648 Bourke Street”,国家限制为澳大利亚。它在下拉列表中向我显示了 5 个结果,第一个结果为“1403/648 Bourke street, Melbourne,Australia”但是当我选择此选项时,我在 place_change 事件监听器中得到的只是“648 Bourke street, Melbourne, Australia”

这个问题是间歇性的,它适用于某些单元地址,但对其他地址无效。任何建议将不胜感激!

4

5 回答 5

12

在我看来,谷歌似乎在验证地址是真实的(至少在他们上次更新地点数据库时是真实的——我猜是政府记录)。问题在于,在创建新的“子前提”地址的地方一直都在发生细分,并且对这些地址的查找似乎更频繁。奇怪的是,他们允许“无效”地址作为自动完成建议,但却限制了结果。

查找下面的悉尼地址将返回“subpremise”和“street_number”

“澳大利亚新南威尔士州悉尼皮特街 9/321 号”

下面的墨尔本地址仅与“路线”一样准确

"2/321 Pitt Street, 不伦瑞克, 维多利亚, 澳大利亚"

最大的问题是结果没有在回复中的任何地方返回单元或街道号码。

我将以下 JS 组合在一起,以将用户输入的地址与返回的结果进行比较。如果缺少“数字”,则会添加它们。您可以根据需要进行自定义以适应您的代码。

if (addressType == 'route') {
    var regex = RegExp('^(.*)'+GPLACESSTREET.split(' ',1)[0]), // get all the user entered values before a match with the first word from the Google result
        result = regex.exec(INPUTFEILD.value);

    if ( Array.isArray(result) ) {
        FULLSTREETADDRESS = result[1]+''+GPLACESSTREET; // add the street name to the user-entered unit & street number
    }
}
于 2015-02-06T03:56:59.270 回答
11

Places Autocomplete API 并非旨在支持“子前提”结果。不久前在https://issuetracker.google.com/35830389的公共问题跟踪器中报告并回答了这一问题

子前提结果的澳大利亚地址看起来与街道地址/前提结果的地址“足够接近”(它们大多以数字开头)。这目前导致 Place Autocomplete 返回可能看起来像子前提结果的内容,但请注意该类型仍然是“路线”:

http://maps.googleapis.com/maps/api/place/autocomplete/json?input=9/321%20Pitt%20Street,%20Sydney

description: "9/321 Pitt Street, Sydney NSW, Australia",
place_id: "Eig5LzMyMSBQaXR0IFN0cmVldCwgU3lkbmV5IE5TVywgQXVzdHJhbGlh",
types: ["route","geocode",],

带有此 place_id 的地点详细信息(和地理编码)请求实际上会找到正确的子前提结果:

https://maps.googleapis.com/maps/api/place/details/json?placeid=Eig5LzMyMSBQaXR0IFN0cmVldCwgU3lkbmV5IE5TVywgQXVzdHJhbGlh

   "result" : {
      "address_components" : [
         {
            "long_name" : "9",
            "short_name" : "9",
            "types" : [ "subpremise" ]
         },
         {
            "long_name" : "321",
            "short_name" : "321",
            "types" : [ "street_number" ]
         },
      ...
      "formatted_address" : "9/321 Pitt St, Sydney NSW 2000, Australia",
      "types" : [ "subpremise" ],

但是,这不能保证适用于所有子前提查询,甚至不能保证长期适用于这个特定的查询。

更可靠的方法是使用 Geocoding API 来搜索预测的“描述”:

https://maps.googleapis.com/maps/api/geocode/json?&address=9%2F321%20Pitt%20St%2C%20Sydney%20NSW%202000%2C%20Australia

   "results" : [
      {
         "address_components" : [
            {
               "long_name" : "9",
               "short_name" : "9",
               "types" : [ "subpremise" ]
            },
            {
               "long_name" : "321",
               "short_name" : "321",
               "types" : [ "street_number" ]
            },
            ...
         ],
         "formatted_address" : "9/321 Pitt St, Sydney NSW 2000, Australia",
         "place_id" : "Eik5LzMyMSBQaXR0IFN0LCBTeWRuZXkgTlNXIDIwMDAsIEF1c3RyYWxpYSIdGhsKFgoUChIJkyPU0z2uEmsR-pmiK6UvZUASATk",
         "types" : [ "subpremise" ]
于 2018-06-07T14:55:14.710 回答
4

谷歌不支持,但你不能阻止客户这样做!

这是一个受@MountainAsh 和@Randell 代码启发的完整函数:

/* Add the unit number (+ fix the street number) if required.
 *
 * Idea from https://stackoverflow.com/questions/17936689/google-places-autocomplete-suggestions-with-unit-no-subpremise-is-not-coming-in
 *
 * Test cases:
 * 9/321 Pitt Street, Sydney, New South Wales, Australia <-- Google throws away the unit number
 * 2/321 Pitt Street, Brunswick, Victoria, Australia <-- Google says street number = 2
 * 1b/123 Clayton Road, Clayton, Victoria, Australia <-- Google says street number = 1
 */
function autofillUnitNumber(txtAutocomplete, txtUnitNumber, txtStreetNumber, txtStreetName) {
    var regex = RegExp("^(.*?)\/(.*?) " + txtStreetName.value); // get all the user entered values before a match with the street name; group #1 = unit number, group #2 = street number
    var results = regex.exec(txtAutocomplete.value);

    if (Array.isArray(results)) { // it was in unit number/street number format
        var unitNumber = results[1]; // group #1 
        var streetNumber = results[2]; // group #2

        txtUnitNumber.value = unitNumber;
        txtStreetNumber.value = streetNumber;
    }
}

在您使用 Google 自动完成功能自动填充您的其他表单字段后调用它,例如:

autofillUnitNumber(
    document.getElementById("txtAutocomplete"),
    document.getElementById("txtUnitNumber"),
    document.getElementById("txtStreetNumber"),
    document.getElementById("txtStreetName"));
于 2019-03-05T05:33:10.090 回答
3

由于我只是想收集单元号并将其添加到街道号,我的解决方案是:

const place = this.AutoComplete.getPlace();
if (isNullOrUndefined(place)) return;

const parts = place.address_components;
const getAddressPart = part => {
  const found = parts.find(p => p.types.indexOf(part) > -1);
  if (found) {
    return found.long_name;
  }

  return null;
};

const address = this.Input.current.value; // input[text] value
let streetNumber = getAddressPart("street_number");

// Regex Match associated
if (streetNumber) {
  const regex = RegExp(`[^\\s,]*(${streetNumber})[^\\s,]*`);
  const foundStreetNumber = regex.exec(address);
  streetNumber = foundStreetNumber[0];
}

const Address = {
  FullAddress: address,
  StreetNumber: streetNumber,
  Street: getAddressPart("route"),
  Suburb: getAddressPart("sublocality"),
  City: getAddressPart("locality"),
  Country: getAddressPart("country"),
  PostCode: getAddressPart("postal_code")
};

这将改进来自 Google Places API 的街道号码数据,以满足以下地址的需求:

4/33 Mokoia Rd, 伯肯黑德, 奥克兰 0626, 新西兰

Proletarska ulica 3/25, Kidričevo, Slovenia(地址可能没有先有街道号码)。

如果没有门牌号,它也不会做任何工作,如果没有单元号,则值将相同。

于 2019-05-10T11:32:03.123 回答
1

对@MountainAsh 的代码稍作修改:

if (addressType == 'route') {
  var regex = RegExp('^(.*?)'+GPLACESSTREET.split(' ',1)[0]), // get all the user entered values before a match with the first word from the Google result
  result = regex.exec(INPUTFEILD.value);

  if ( Array.isArray(result) ) {
    FULLSTREETADDRESS = result[1]+''+GPLACESSTREET; // add the street name to the user-entered unit & street number
  }
}

注意额外的? RegExp中,这使得搜索不贪婪地涵盖街道名称以相同的郊区名称开头的情况(例如 123 Clayton Rd, Clayton)。

于 2017-09-06T04:56:56.467 回答