如何让Maxmind的Geoip数据库与Postgres + Heroku一起使用

时间:2012-04-30 12:21:07

标签: ruby-on-rails-3 postgresql heroku geoip

此处有人在Rails 3 +,Heroku,Pgsql上运行并使用Maxmind's Geoip数据库吗?

在MySql上,我能够通过以下方式获得一个简单的查询:

IpToCountry.where('ip_to_countries.ip_number_to >= INET_ATON(?)', '24.24.24.24').order('ip_number_to ASC').limit(1).first

然而,自从转移到Pgsql,我试图找到一种方法来正确查询数据库。到目前为止,我有:

remote_ip_array = '24.24.24.24'.split('.')
remote_ip_number = 16777216*remote_ip_array[0].to_i + 65536*remote_ip_array[1].to_i + 256*remote_ip_array[2].to_i + remote_ip_array[3].to_i
ip_to_country = IpToCountry.where('? >= ip_number_from AND ? <= ip_number_to', remote_ip_number, remote_ip_number).order('ip_number_to ASC').limit(1).first

上述查询的问题是某些IP不匹配。例如:37.59.16.123108.166.92.235

我查看了ip4r,但由于我使用http://postgres.heroku.com,我可能无法安装此选项。我向支持小组发送了一封电子邮件进行验证。

与此同时,我们非常感谢任何其他反馈。

1 个答案:

答案 0 :(得分:1)

ip4r本身不太可能有助于匹配。如果您需要针对子网的GIN索引,则通常需要ip4r,例如,强制执行存储CIDR块不能重叠的约束。

您有两种选择。第一个也是最好的一个是使用PostgreSQLs inet类型并将ipv4地址存储在inet类型中。然后你会使用标准的文本表示。例如,比较:

select '10.59.3.1'::text > '101.3.4.1';
 ?column? 
----------
 t
(1 row)

select '10.59.3.1'::inet > '101.3.4.1';
 ?column? 
----------
 f
(1 row)

此类型包含在vanilla PostgreSQL中,因此您不需要插件。

第二个选项是创建一个int(inet)函数:

CREATE OR REPLACE FUNCTION to_int(inet) RETURNS bigint LANGUAGE SQL IMMUTABLE AS $$
SELECT $1 - '0.0.0.0';
$$;

然后

select to_int('10.0.0.1');
  to_int   
-----------
 167772161
(1 row)

这样你就可以在数据库中执行ipv4到int。

我会推荐inet类型。他们真的很有帮助。大多数用例都不需要ip4r。