davidmoten/geo

repository·master·Indexed 19 days ago

https://github.com/davidmoten/geo

A high-performance Java utility library for geohashing. It provides thread-safe methods for encoding and decoding coordinates, finding adjacent hashes, and calculating geohash coverage for bounding box searches to optimize spatial queries in databases.

Tokens
880
Snippets
3
Records
5
Agent score
16%

What's inside geo

  1. Core Geohashing API Overview

    master

    The geo library provides high-performance, thread-safe utility methods for geohashing. Key capabilities include:

    • Encoding: Convert latitude and longitude to geohashes of arbitrary length using GeoHash.encodeHash.
    • Decoding: Convert geohashes back to latitude and longitude using GeoHash.decodeHash.
    • Adjacency: Find a single adjacent hash in any direction (including poles) via GeoHash.adjacentHash, or find all 8 neighbors using GeoHash.neighbours.
    • Bounding Box Support:
      • Calculate the required hash length to enclose a bounding box with GeoHash.hashLengthToCoverBoundingBox.
      • Generate a set of geohashes that cover a bounding box along with their coverage ratio using GeoHash.coverBoundingBox.
    • Dimensions: Calculate the height and width of a geohash in degrees using GeoHash.heightDegrees and GeoHash.widthDegrees.
    • Base32 Conversion: Encode and decode long values from geohashes using Base32.encodeBase32 and Base32.decodeBase32.
  2. Perform efficient bounding box searches using geohashes

    master

    To avoid performance degradation in databases that struggle with multiple inequality conditions (like latitude and longitude ranges), you can rewrite bounding box queries using geohashes. This allows you to use a single range condition (e.g., time) and an equality condition against a set of geohashes.

    Workflow:

    1. Store Geohashes: Store geohashes of a fixed length in an indexed field for every position in your database. (Tip: Converting hashes to long via Base32.decodeBase32 can be advantageous for storage).
    2. Calculate Coverage: Use GeoHash.coverBoundingBox to find the set of geohashes that wholly cover your target bounding box.
    3. Query: Perform a query using your primary range condition (e.g., time) and an OR condition against the calculated geohashes.
      • Example logic: (startTime <= t < finishTime) and (hash='drt' or hash='dr2')
    4. Filter: Since the geohash set might be slightly larger than the actual bounding box, perform a final filter on the results to ensure they fall strictly within the lat-long bounds.
    (startTime <= t < finishTime) and (hash3='drt' or hash3='dr2')
  3. Install the geo library via Maven

    master

    To use the geo library in your Java project, add the following dependency to your pom.xml file. Replace VERSION_HERE with the desired version (e.g., 0.8.1).

    <dependency>
        <groupId>com.github.davidmoten</groupId>
        <artifactId>geo</artifactId>
        <version>VERSION_HERE</version>
    </dependency>
  4. Configure geohash coverage for bounding boxes

    master

    When using GeoHash.coverBoundingBox, you can control the number of hashes returned to balance between query complexity and precision.

    • Default Behavior: Calling GeoHash.coverBoundingBox with only bounding points returns a number of hashes up to GeoHash.DEFAULT_MAX_HASHES (which is 12).
    • Custom Limit: Use GeoHash.coverBoundingBoxMaxHashes to explicitly set the maximum number of hashes allowed to cover the area.

    Choosing the right maxHashes depends on your database performance. For example, benchmarks on an H2 database suggested an optimal query time when maxHashes was approximately 700.