【问题标题】:How to transform IP addresses into geolocation in BigQuery standard SQL?如何在 BigQuery 标准 SQL 中将 IP 地址转换为地理位置?
【发布时间】:2018-02-14 04:47:38
【问题描述】:

所以我读过https://cloudplatform.googleblog.com/2014/03/geoip-geolocation-with-google-bigquery.html

但我想知道是否有 #standardSQL 这样做的方式。到目前为止,我在转换 PARSE_IP 和 NTH() 时遇到了很多挑战,因为迁移文档中建议的更改有局限性。

PARSE_IP(contributor_ip)NET.IPV4_TO_INT64(NET.SAFE_IP_FROM_STRING(contributor_ip)) 不适用于 IPv6 IP 地址。

NTH(1, latitude) latlatitude[SAFE_ORDINAL(1)] 不起作用,因为纬度被视为一个字符串。

而且我可能还没有遇到更多的迁移问题。有谁知道如何在 BigQuery 标准 SQL 中将 IP 地址转换为地理位置?

附:我将如何从地理定位到确定时区?

编辑:那么这有什么区别

#legacySQL
SELECT
  COUNT(*) c,
  city,
  countryLabel,
  NTH(1, latitude) lat,
  NTH(1, longitude) lng
FROM (
  SELECT
    INTEGER(PARSE_IP(contributor_ip)) AS clientIpNum,
    INTEGER(PARSE_IP(contributor_ip)/(256*256)) AS classB
  FROM
    [publicdata:samples.wikipedia]
  WHERE
    contributor_ip IS NOT NULL ) AS a
JOIN EACH
  [fh-bigquery:geocode.geolite_city_bq_b2b] AS b
ON
  a.classB = b.classB
WHERE
  a.clientIpNum BETWEEN b.startIpNum
  AND b.endIpNum
  AND city != ''
GROUP BY
  city,
  countryLabel
ORDER BY
  1 DESC

SELECT
  COUNT(*) c,
  city,
  countryLabel,
  ANY_VALUE(latitude) lat,
  ANY_VALUE(longitude) lng
FROM (
  SELECT
    CASE
      WHEN BYTE_LENGTH(contributor_ip) < 16 THEN SAFE_CAST(NET.IPV4_TO_INT64(NET.SAFE_IP_FROM_STRING(contributor_ip)) AS INT64)
      ELSE NULL
    END AS clientIpNum,
    CASE
      WHEN BYTE_LENGTH(contributor_ip) < 16 THEN SAFE_CAST(NET.IPV4_TO_INT64(NET.SAFE_IP_FROM_STRING(contributor_ip)) / (256*256) AS INT64) 
      ELSE NULL
    END AS classB
  FROM
    `publicdata.samples.wikipedia`
  WHERE
    contributor_ip IS NOT NULL ) AS a
JOIN
  `fh-bigquery.geocode.geolite_city_bq_b2b` AS b
ON
  a.classB = b.classB
WHERE
  a.clientIpNum BETWEEN b.startIpNum
  AND b.endIpNum
  AND city != ''
GROUP BY
  city,
  countryLabel
ORDER BY
  1 DESC

edit2:似乎我设法通过不正确地投射浮点数来解决问题。目前,标准 SQL 返回 41815 行,而不是旧 SQL 中的 56347 行,这可能是由于标准 SQL 缺少从 IPv6 到 int 的转换,但也可能是由于其他原因。此外,旧版 SQL 查询的性能要好得多,运行时间约为 10 秒,而不是标准 SQL 的整分钟。

【问题讨论】:

  • NTHarr[OFFSET(0)] 的类似物。如果没有数组,则不需要使用ORDINALOFFSET。如果您只想要 IPv4,您可以使用 LENGTH(...) 过滤 IP。
  • Error: Element access using [] is not supported on values of type STRING
  • 这就是我的意思——你有一个字符串而不是一个数组,所以你不需要使用它。
  • 可以按列表添加到组中,也可以使用ANY_VALUE

标签: timezone google-bigquery geoip ip-geolocation bigquery-standard-sql


【解决方案1】:

根据https://gist.github.com/matsukaz/a145c2553a0faa59e32ad7c25e6a92f7

#standardSQL
SELECT
  id,
  IFNULL(city, 'Other') AS city,
  IFNULL(countryLabel, 'Other') AS countryLabel,
  latitude,
  longitude
FROM (
  SELECT
    id,
    NET.IPV4_TO_INT64(NET.IP_FROM_STRING(ip)) AS clientIpNum,
    TRUNC(NET.IPV4_TO_INT64(NET.IP_FROM_STRING(ip))/(256*256)) AS classB
  FROM
    `<project>.<dataset>.log` ) AS a
LEFT OUTER JOIN
  `fh-bigquery.geocode.geolite_city_bq_b2b` AS b
ON
  a.classB = b.classB
  AND a.clientIpNum BETWEEN b.startIpNum AND b.endIpNum
ORDER BY
  id ASC

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-20
    • 2013-05-09
    • 2021-03-17
    • 2013-12-17
    • 1970-01-01
    • 2013-03-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多