Switch branches/tags
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
110 lines (88 sloc) 2.64 KB

Maxminddb is an OCaml binding to libmaxminddb, the successor of GeoIP Legacy (Previously known as GeoIP).

Lookups return polymorphic variants wrapping values like bool, float, string and int.

Note I assume you have libmaxminddb already installed on your system, on OS X this is easily done with brew install libmaxminddb, for other platforms checkout the installation instructions at the libmaxminddb repo.

Once you have the library on your machine, install the OCaml side with:

opam install maxminddb

Code Examples

Here's a short example of what you can do with the library.

(* File named *)
#require "maxminddb"

let () =
  let some_ip = "" in
  let this_mmdb = Maxminddb.create "etc/GeoLite2-City.mmdb" in
  let loc = Maxminddb.location some_ip this_mmdb in
  let open Maxminddb in
  Printf.sprintf "%f %f %d %s" loc.latitude loc.longitude loc.metro_code loc.time_zone
  |> print_endline;
  let geo_borders = borders ~lang:French ~ip:some_ip this_mmdb in
    "%s %s %s %s %s"
  |> print_endline

And the corresponding result on the shell

$ utop
33.895900 -118.220100 803 America/Los_Angeles
90221 Compton États-Unis Amérique du Nord US

Here's dumping example

(* This file is named *)
#require "maxminddb"

let () =
  Maxminddb.create "etc/GeoLite2-City.mmdb"
  |> Maxminddb.dump Sys.argv.(1) |> print_endline

And at the shell

$ utop ""
          5339066 <uint32>
              "Compton" <utf8_string>
              "康普顿" <utf8_string>

Also note that you can query the IP database by array indexing as well.

(* This file is named *)
#require "maxminddb"

let () =
  let some_ip = "" in
  let this_mmdb = Maxminddb.create "etc/GeoLite2-City.mmdb" in
  match Maxminddb.lookup_path some_ip ["subdivisions";"0";"geoname_id"] this_mmdb with
  | `Int i -> string_of_int i |> print_endline
  | _ -> assert false
$ utop


  1. If your path yields a map or array then the library will throw an exception, this is mostly an implementation issue. I haven't thought about how I want to do it yet.