如何从 CIDR BigQuery 获取发件人和收件人 IP 地址
How to get From & To Ip Address from CIDR BigQuery
BigQuery 提供更新的 geoip2 public 数据集 here [bigquery-publicdata -> geolite2 -> ipv4_city_blocks] 其中包含具有 IPv4 CIDR 值的网络列。
如何通过 BigQuery SQL(而不是通过 BigQuery 外部的实用程序)将网络列中的 CIDR 值转换为开始和结束 ip-address 值,以便我可以找到 IP 地址是否是在一个范围内或没有?如果您可以提供查询以获取 table.
中 CIDR 值的范围 ips,将会很有帮助
首先要检查的是,如果那个函数已经存在,那么请参考BigQuery Functions and Operators documentation。
如果没有,您需要使用 Standard SQL User-Defined Functions (UDF),它允许您使用另一个 SQL 表达式或其他编程语言创建一个函数,例如 JavaScript。
请记住,在使用 UDF JavaScript 函数时,BigQuery 会在每个执行分片上使用函数的内容初始化一个 JavaScript 环境。没有避免加载环境的优化,因此它会减慢查询速度。
有关 GeoIP2 City and Country CSV Databases site, there is a utility to convert 'network' column to start/end IPs or start/end integers. Refer to Github 站点的详细信息。
此查询将完成工作:
# replace with your source of IP addresses
# here I'm using the same Wikipedia set from the previous article
WITH source_of_ip_addresses AS (
SELECT REGEXP_REPLACE(contributor_ip, 'xxx', '0') ip, COUNT(*) c
FROM `publicdata.samples.wikipedia`
WHERE contributor_ip IS NOT null
GROUP BY 1
)
SELECT city_name, SUM(c) c, ST_GeogPoint(AVG(longitude), AVG(latitude)) point
FROM (
SELECT ip, city_name, c, latitude, longitude, geoname_id
FROM (
SELECT *, NET.SAFE_IP_FROM_STRING(ip) & NET.IP_NET_MASK(4, mask) network_bin
FROM source_of_ip_addresses, UNNEST(GENERATE_ARRAY(9,32)) mask
WHERE BYTE_LENGTH(NET.SAFE_IP_FROM_STRING(ip)) = 4
)
JOIN `fh-bigquery.geocode.201806_geolite2_city_ipv4_locs`
USING (network_bin, mask)
)
WHERE city_name IS NOT null
GROUP BY city_name, geoname_id
ORDER BY c DESC
LIMIT 5000`
查找更多详细信息:
以下适用于 BigQuery 标准 SQL
#standardSQL
CREATE TEMP FUNCTION cidrToRange(CIDR STRING)
RETURNS STRUCT<start_IP STRING, end_IP STRING>
LANGUAGE js AS """
var beg = CIDR.substr(CIDR,CIDR.indexOf('/'));
var end = beg;
var off = (1<<(32-parseInt(CIDR.substr(CIDR.indexOf('/')+1))))-1;
var sub = beg.split('.').map(function(a){return parseInt(a)});
var buf = new ArrayBuffer(4);
var i32 = new Uint32Array(buf);
i32[0] = (sub[0]<<24) + (sub[1]<<16) + (sub[2]<<8) + (sub[3]) + off;
var end = Array.apply([],new Uint8Array(buf)).reverse().join('.');
return {start_IP: beg, end_IP: end};
""";
SELECT network, IP_range.*
FROM `bigquery-public-data.geolite2.ipv4_city_blocks`,
UNNEST([cidrToRange(network)]) IP_range
处理所有 3,037,858 行大约需要 60 秒,结果如下
BigQuery 提供更新的 geoip2 public 数据集 here [bigquery-publicdata -> geolite2 -> ipv4_city_blocks] 其中包含具有 IPv4 CIDR 值的网络列。
如何通过 BigQuery SQL(而不是通过 BigQuery 外部的实用程序)将网络列中的 CIDR 值转换为开始和结束 ip-address 值,以便我可以找到 IP 地址是否是在一个范围内或没有?如果您可以提供查询以获取 table.
中 CIDR 值的范围 ips,将会很有帮助首先要检查的是,如果那个函数已经存在,那么请参考BigQuery Functions and Operators documentation。
如果没有,您需要使用 Standard SQL User-Defined Functions (UDF),它允许您使用另一个 SQL 表达式或其他编程语言创建一个函数,例如 JavaScript。
请记住,在使用 UDF JavaScript 函数时,BigQuery 会在每个执行分片上使用函数的内容初始化一个 JavaScript 环境。没有避免加载环境的优化,因此它会减慢查询速度。
有关 GeoIP2 City and Country CSV Databases site, there is a utility to convert 'network' column to start/end IPs or start/end integers. Refer to Github 站点的详细信息。
此查询将完成工作:
# replace with your source of IP addresses
# here I'm using the same Wikipedia set from the previous article
WITH source_of_ip_addresses AS (
SELECT REGEXP_REPLACE(contributor_ip, 'xxx', '0') ip, COUNT(*) c
FROM `publicdata.samples.wikipedia`
WHERE contributor_ip IS NOT null
GROUP BY 1
)
SELECT city_name, SUM(c) c, ST_GeogPoint(AVG(longitude), AVG(latitude)) point
FROM (
SELECT ip, city_name, c, latitude, longitude, geoname_id
FROM (
SELECT *, NET.SAFE_IP_FROM_STRING(ip) & NET.IP_NET_MASK(4, mask) network_bin
FROM source_of_ip_addresses, UNNEST(GENERATE_ARRAY(9,32)) mask
WHERE BYTE_LENGTH(NET.SAFE_IP_FROM_STRING(ip)) = 4
)
JOIN `fh-bigquery.geocode.201806_geolite2_city_ipv4_locs`
USING (network_bin, mask)
)
WHERE city_name IS NOT null
GROUP BY city_name, geoname_id
ORDER BY c DESC
LIMIT 5000`
查找更多详细信息:
以下适用于 BigQuery 标准 SQL
#standardSQL
CREATE TEMP FUNCTION cidrToRange(CIDR STRING)
RETURNS STRUCT<start_IP STRING, end_IP STRING>
LANGUAGE js AS """
var beg = CIDR.substr(CIDR,CIDR.indexOf('/'));
var end = beg;
var off = (1<<(32-parseInt(CIDR.substr(CIDR.indexOf('/')+1))))-1;
var sub = beg.split('.').map(function(a){return parseInt(a)});
var buf = new ArrayBuffer(4);
var i32 = new Uint32Array(buf);
i32[0] = (sub[0]<<24) + (sub[1]<<16) + (sub[2]<<8) + (sub[3]) + off;
var end = Array.apply([],new Uint8Array(buf)).reverse().join('.');
return {start_IP: beg, end_IP: end};
""";
SELECT network, IP_range.*
FROM `bigquery-public-data.geolite2.ipv4_city_blocks`,
UNNEST([cidrToRange(network)]) IP_range
处理所有 3,037,858 行大约需要 60 秒,结果如下