如何在GeoLite2的块表中找到我的IP地址

时间:2014-06-17 13:37:06

标签: postgresql geoip maxmind cidr

在PostgreSQL DB中我有表blocks,它是从GeoLite2-City-Blocks.csv导入的,具有以下结构:

network_start_ip cidr NOT NULL,
network_mask_length integer NOT NULL,
geoname_id bigint,
registered_country_geoname_id bigint,
represented_country_geoname_id bigint,
postal_code character(50),
latitude DOUBLE PRECISION,
longitude DOUBLE PRECISION,
is_anonymous_proxy boolean,
is_satellite_provider boolean

存储IP地址使用的是CIDR数据类型,但是在GeoLite2-City-Blocks.csv中只有START_IP_ADDRESS和MASK_LENGTH。

此表中的数据示例:

::ffff:1.0.0.0/128   120    2077456     2077456  ....

如何选择包含我的IP地址的行,例如87.197.148.121?是否需要计算END_IP_ADDRESS来分隔列?

1 个答案:

答案 0 :(得分:0)

您将要使用inet / cidr的包含运算符:

select * from blocks
where set_masklen(network_start_ip,network_mask_length) >>= '::ffff:87.197.148.121'::inet;

有几个问题。首先,数据表示将网络和掩码拆分为不同的字段,因此该查询效率非常低。这两个字段可以简单地组合如下:

alter table blocks add column net_ip inet;

然后会有一次数据迁移:

update blocks set net_ip = set_masklen(network_start_ip,network_mask_length);

然后上面的查询将更容易理解:

select * from blocks where net_ip >>= '87.197.148.121'::inet;

但是,我仍然认为此查询无效,因为net_ip数据以ipv6表示,比较在ip4v中。您可以编写转换函数,或者:

select * from blocks where net_ip >>= concat('::ffff:', '87.197.148.121')::inet;

这根本不是最佳选择。 net_ip未编入索引。要做到这一点,你需要ip4r扩展为postgres。