Skip to content

Commit

Permalink
Initial plugin version
Browse files Browse the repository at this point in the history
  • Loading branch information
gornik committed Oct 16, 2013
1 parent faa04a4 commit d41f1c5
Show file tree
Hide file tree
Showing 12 changed files with 862 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
target
.idea
*.iml
*.jar
*.class
94 changes: 94 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,96 @@
gorgeo
======

Provides a facet for grouping documents containing geolocation data based on
the geohash cells. It groups the geographical points by using
[geohash](http://en.wikipedia.org/wiki/Geohash) cells, according to the
level provided by user.

### Installation

TODO

### Example usage

Query example:

```json
"geohashcell": {
"field": "location",
"level" : 3,
"top_left": "11.21,51.33",
"bottom_right": "-20.21,80.65"
}
```



Result example:

```json
"facets": {
"f": {
"_type": "Z2VvaGFzaGNlbGw=",
"field": "location",
"top_left": "[11.21, 51.33]",
"bottom_right": "[-20.21, 80.65]",
"level": 4,
"base_map_level": 1,
"counts": {
"[8.876953125, 76.46484375]": "1",
"[6.240234375, 79.98046875]": "1",
"[6.943359375, 79.98046875]": "13",
"[9.755859375, 77.87109375]": "2",
"[2.197265625, 72.94921875]": "1",
"[9.931640625, 77.51953125]": "3",
...
}
}
```

### Parameters

| Parameter name | Optional | Default value | Description
| ---------------- | :--------: | :---------------: | -------------
| __field__ | _optional_ | "location" | Name of the document field containing geographical location.
| __top_left__ | _optional_ | "90,-180" | Geographical coordinates (lattitude, longitude) of the top left point of the current map viewport.
| __bottom_right__ | _optional_ | "-90,180" | Geographical coordinates (lattitude, longitude) of the bottom right point of the current map viewport.
| __level__ | _optional_ | 3 | The grouping level (see [Algorithm](#Algorithm)).

_Note_: the map viewport defaults to a full map.

### Results

* __field__ - equal to the __field__ parameter
* __top_left__ - equal to the __top_left__ parameter
* __bottom_right__ - equal to the __bottom_right__ parameter
* __level__ - actual grouping level (see [Algorithm](#Algorithm))
* __base_map_level__ - base grouping level for the current map viewport
* __counts__ - grouping results, contain cell center and corresponding
document count

### Algorithm

The facet counts the documents based on geohash prefixes. For more information
on how geohashing works, see the following links:

* [Wikipedia on Geohash](http://en.wikipedia.org/wiki/Geohash)
* [Visualizing Geohash](http://www.bigdatamodeling.org/2013/01/intuitive-geohash.html)

The algorithm groups documents based on geohash prefixes of the stored
geographical data. The __level__ parameter provided to the facet is used as
a lenght of the geohash prefix for grouping, i.e. increasing the level by one,
divides the map into 32 cells.

Additionally the facet adapts to the current map viewport by comparing the
current viewport size with sizes of the geohash cells and calculates the
__base_map_level__. This level is than added to the level parameter and used
as a geohash prefix. The result is always in [1,6] range.

### To do
* better parameter checking
* more tests

Credits
=======
Thanks to [Mahesh Paolini-Subramanya](https://github.com/dieswaytoofast) for his help.
29 changes: 29 additions & 0 deletions assembly/release.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<?xml version="1.0"?>
<assembly>
<id>bin</id>
<formats>
<format>zip</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>false</unpack>
<outputDirectory>/</outputDirectory>
<useProjectArtifact>false</useProjectArtifact>
<useTransitiveFiltering>true</useTransitiveFiltering>
<excludes>
<exclude>org.elasticsearch:elasticsearch</exclude>
<exclude>junit:junit</exclude>
</excludes>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<directory>${project.build.directory}/</directory>
<outputDirectory>/</outputDirectory>
<includes>
<include>elasticsearch-${project.name}-${elasticsearch.version}.jar</include>
</includes>
</fileSet>
</fileSets>
</assembly>
122 changes: 122 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.elasticsearch.plugin.geohashcellfacet</groupId>
<artifactId>GeoHashCellFacetPlugin</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<name>GeoHashCellFacetPlugin</name>
<url>http://maven.apache.org</url>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3</version>
<configuration>
<finalName>
elasticsearch-${project.name}-${elasticsearch.version}
</finalName>
</configuration>
</plugin>
<!-- Copy dependencies into lib folder -->
<!-- To see full classpath use mvn dependency:build-classpath -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/lib
</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- Skip Surefire tests -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.8</version>
<configuration>
<skipTests>true</skipTests>
<additionalClasspathElements>
<additionalClasspathElement>
${project.build.directory}/classes/conf
</additionalClasspathElement>
<additionalClasspathElement>
${project.build.directory}/lib
</additionalClasspathElement>
</additionalClasspathElements>
</configuration>
</plugin>
<!-- Generate the release zip file (run during package step) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<configuration>
<finalName>
elasticsearch-${project.name}-${elasticsearch.version}
</finalName>
<appendAssemblyId>false</appendAssemblyId>
<outputDirectory>${project.build.directory}/release/
</outputDirectory>
<descriptors>
<descriptor>assembly/release.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>generate-release-plugin</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
</includes>
</resource>
</resources>
</build>

<properties>
<elasticsearch.version>0.90.5</elasticsearch.version>
</properties>

<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
</dependency>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>${elasticsearch.version}</version>
</dependency>
</dependencies>
<repositories>
<repository>
<id>sonatype</id>
<name>Sonatype Groups</name>
<url>https://oss.sonatype.org/content/groups/public/</url>
</repository>
</repositories>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package org.elasticsearch.plugin.geohashcellfacet;

import org.elasticsearch.common.geo.GeoHashUtils;
import org.elasticsearch.common.geo.GeoPoint;

/**
* Represents a cell established by the geo hash prefix.
*/
public class GeoHashCell {
public final static int MIN_GEOHASH_LEVEL = 1;
public final static int MAX_GEOHASH_LEVEL = 6;

private final String geoHashPrefix;
private final GeoPoint topLeft = new GeoPoint();
private final GeoPoint bottomRight = new GeoPoint();

/**
* Creates a geo hash cell of the provided level which includes the given point.
*
* @param point Point which should be included in this cell.
* @param level Level for the cell, i.e. the length of the geo hash.
*/
public GeoHashCell(GeoPoint point, int level) {
this(GeoHashUtils.encode(point.lat(), point.lon()).substring(0, level));
}

/**
* Creates a geo hash cell instance based on the given geo hash prefix.
* @param geoHashPrefix Prefix for the geo hash cell.
*/
public GeoHashCell(String geoHashPrefix) {
if (geoHashPrefix == null || geoHashPrefix.isEmpty())
throw new IllegalArgumentException("GeoHash value is required");
this.geoHashPrefix = geoHashPrefix;

GeoHashUtils.decodeCell(geoHashPrefix, topLeft, bottomRight);
}

/**
* Gets the point which is a center of this geo hash cell.
* @return Center of this cell.
*/
public GeoPoint getCenter() {
return new GeoPoint(
(topLeft.lat() + bottomRight.lat()) / 2D,
(topLeft.lon() + bottomRight.lon()) / 2D
);
}

/**
* Compare if this object equals another object.
* @param o Object to compare.
* @return True if objects are equal, otherwise false.
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;

GeoHashCell that = (GeoHashCell) o;

return geoHashPrefix.equals(that.geoHashPrefix);
}

/**
* Gets a hash code of this instance.
* @return Hash code.
*/
@Override
public int hashCode() {
return geoHashPrefix.hashCode();
}

/**
* Gets a string representation of this instance.
* @return String representation.
*/
@Override
public String toString() {
return getCenter().toString();
}
}
Loading

0 comments on commit d41f1c5

Please sign in to comment.