Now we have all of the data loaded in, we need to be able to search on it. In order to do that, we define the following index:
It is a very simple one, mapping the start and end of each range for each location.
The next step is actually doing the search, and this is where we run into some issues. The problem was with the data:
Let us take the first range and translate that to IP addresses in the format that you are probably more used to:
Start: 0.177.195.68 End: 255.177.195.68
Yep, it is little endian vs. big endian here to bite us once more.
It took me a while to figure it out, I’ll admit. In other words, we have to reverse the IP address before we can search on it properly. Thankfully, that is easily done, and we have the following masterpiece:
The data source that we have only support IPv4, so that is what we allow. We reverse the IP, then do a range search based on this.
Now we can use it like this:
var location = session.GetLocationByIp(IPAddress.Parse("18.104.22.168"));
Which tells us that this is a Mountain View, CA, USA address.
More importantly for our purposes, it tells us that this is located at: 37.4192, -122.0574 We will use that shortly to do spatial searches for RavenDB events near you, which I’ll discuss in my next post.
Oh, and just for fun. You might remember that in previous posts I mentioned that MaxMind (the source for this geo location information) had to create its own binary format because relational databases took several second to process each query?
The query above completed in 53 milliseconds on my machine, without any tuning on our part. And that is before we introduce caching into the mix.