Skip to content

Commit

Permalink
[Geo API 645] Updated $geoIntersects API so it takes any geomtetry o…
Browse files Browse the repository at this point in the history
…bject, and created tests for line and polygon to show how to use the API. Fixes MorphiaOrg#645.
  • Loading branch information
trishagee committed Mar 21, 2015
1 parent a2e4235 commit d5cc107
Show file tree
Hide file tree
Showing 4 changed files with 468 additions and 6 deletions.
9 changes: 5 additions & 4 deletions morphia/src/main/java/org/mongodb/morphia/query/FieldEnd.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.mongodb.morphia.query;


import org.mongodb.morphia.geo.Geometry;
import org.mongodb.morphia.geo.MultiPolygon;
import org.mongodb.morphia.geo.Point;
import org.mongodb.morphia.geo.Polygon;
Expand Down Expand Up @@ -121,11 +122,11 @@ public interface FieldEnd<T> {

/**
* This performs a $geoIntersects query, searching documents containing any sort of GeoJson field and returning
* those where the given point intersects with the document shape. This includes cases where the data and the
* those where the given geometry intersects with the document shape. This includes cases where the data and the
* specified object share an edge.
*
* @param point the co-ordinates to use to find any intersecting shapes.
* @return any documents where the GeoJson intersects with a specified {@code point}.
* @param geometry the shape to use to query for any stored shapes that intersect
* @return any documents where the GeoJson intersects with a specified {@code geometry}.
*/
T intersects(Point point);
T intersects(Geometry geometry);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.mongodb.morphia.query;


import org.mongodb.morphia.geo.Geometry;
import org.mongodb.morphia.geo.MultiPolygon;
import org.mongodb.morphia.geo.Point;
import org.mongodb.morphia.geo.Polygon;
Expand Down Expand Up @@ -231,8 +232,8 @@ public T type(final Type type) {
}

@Override
public T intersects(final Point point) {
target.add(new StandardGeoFieldCriteria(query, field, INTERSECTS, point, null, validateName, false));
public T intersects(final Geometry geometry) {
target.add(new StandardGeoFieldCriteria(query, field, INTERSECTS, geometry, null, validateName, false));
return target;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
package org.mongodb.morphia.query;

import org.junit.Before;
import org.junit.Test;
import org.mongodb.morphia.TestBase;
import org.mongodb.morphia.geo.AllTheThings;
import org.mongodb.morphia.geo.Area;
import org.mongodb.morphia.geo.City;
import org.mongodb.morphia.geo.LineString;
import org.mongodb.morphia.geo.Regions;
import org.mongodb.morphia.geo.Route;

import java.util.List;

import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mongodb.morphia.geo.GeoJson.geometryCollection;
import static org.mongodb.morphia.geo.GeoJson.lineString;
import static org.mongodb.morphia.geo.GeoJson.multiPoint;
import static org.mongodb.morphia.geo.GeoJson.multiPolygon;
import static org.mongodb.morphia.geo.GeoJson.point;
import static org.mongodb.morphia.geo.GeoJson.polygon;

public class GeoIntersectsQueriesWithLineTest extends TestBase {
@Before
public void setUp() {
// this whole test class is designed for "modern" geo queries
checkMinServerVersion(2.4);
super.setUp();
}

@Test
public void shouldFindAPointThatLiesOnTheQueryLine() {
// given
LineString spanishLine = lineString(point(37.40759155713022, -5.964911067858338),
point(37.3753708, -5.9550582));
City manchester = new City("Manchester", point(53.4722454, -2.2235922));
getDs().save(manchester);
City london = new City("London", point(51.5286416, -0.1015987));
getDs().save(london);
City sevilla = new City("Sevilla", point(37.3753708, -5.9550582));
getDs().save(sevilla);

getDs().ensureIndexes();

// when
List<City> matchingCity = getDs().find(City.class)
.field("location")
.intersects(spanishLine)
.asList();

// then
assertThat(matchingCity.size(), is(1));
assertThat(matchingCity.get(0), is(sevilla));
}

@Test
public void shouldFindRoutesThatALineCrosses() {
// given
Route sevilla = new Route("Spain", lineString(point(37.4045286, -5.9642332),
point(37.4061095, -5.9645765)));
getDs().save(sevilla);
Route newYork = new Route("New York", lineString(point(40.75981395319104, -73.98302106186748),
point(40.7636824529618, -73.98049869574606),
point(40.76962974853814, -73.97964206524193)));
getDs().save(newYork);
Route london = new Route("London", lineString(point(51.507780365645885, -0.21786745637655258),
point(51.50802478194237, -0.21474729292094707),
point(51.5086863655597, -0.20895397290587425)));
getDs().save(london);
Route londonToParis = new Route("London To Paris", lineString(point(51.5286416, -0.1015987),
point(48.858859, 2.3470599)));
getDs().save(londonToParis);
getDs().ensureIndexes();

// when
List<Route> routeContainingPoint = getDs().find(Route.class)
.field("route")
.intersects(lineString(point(37.4043709, -5.9643244),
point(37.4045286, -5.9642332)))
.asList();

// then
assertThat(routeContainingPoint.size(), is(1));
assertThat(routeContainingPoint.get(0), is(sevilla));
}

@Test
public void shouldFindAreasThatALineCrosses() {
// given
Area sevilla = new Area("Spain",
polygon(point(37.40759155713022, -5.964911067858338),
point(37.40341208875179, -5.9643941558897495),
point(37.40297396667302, -5.970452763140202),
point(37.40759155713022, -5.964911067858338))
);
getDs().save(sevilla);
Area newYork = new Area("New York",
polygon(point(40.75981395319104, -73.98302106186748),
point(40.7636824529618, -73.98049869574606),
point(40.76962974853814, -73.97964206524193),
point(40.75981395319104, -73.98302106186748)));
getDs().save(newYork);
Area london = new Area("London",
polygon(point(51.507780365645885, -0.21786745637655258),
point(51.50802478194237, -0.21474729292094707),
point(51.5086863655597, -0.20895397290587425),
point(51.507780365645885, -0.21786745637655258)));
getDs().save(london);
getDs().ensureIndexes();

// when
List<Area> areaContainingPoint = getDs().find(Area.class)
.field("area")
.intersects(lineString(point(37.4056048, -5.9666089),
point(37.404497, -5.9640557)))
.asList();

// then
assertThat(areaContainingPoint.size(), is(1));
assertThat(areaContainingPoint.get(0), is(sevilla));
}

@Test
public void shouldFindRegionsThatALineCrosses() {
checkMinServerVersion(2.6);
// given
Regions sevilla = new Regions("Spain", multiPolygon(polygon(point(37.40759155713022, -5.964911067858338),
point(37.40341208875179, -5.9643941558897495),
point(37.40297396667302, -5.970452763140202),
point(37.40759155713022, -5.964911067858338)),
polygon(point(37.38744598813355, -6.001141928136349),
point(37.385990973562, -6.002588979899883),
point(37.386126928031445, -6.002463921904564),
point(37.38744598813355, -6.001141928136349))));
getDs().save(sevilla);

Regions usa = new Regions("US", multiPolygon(polygon(point(40.75981395319104, -73.98302106186748),
point(40.7636824529618, -73.98049869574606),
point(40.76962974853814, -73.97964206524193),
point(40.75981395319104, -73.98302106186748)),
polygon(point(28.326568258926272, -81.60542246885598),
point(28.327541397884488, -81.6022228449583),
point(28.32950334995985, -81.60564735531807),
point(28.326568258926272, -81.60542246885598))));
getDs().save(usa);

Regions london = new Regions("London", multiPolygon(polygon(point(51.507780365645885, -0.21786745637655258),
point(51.50802478194237, -0.21474729292094707),
point(51.5086863655597, -0.20895397290587425),
point(51.507780365645885, -0.21786745637655258)),
polygon(point(51.498216362670064, 0.0074849557131528854),
point(51.49176875129342, 0.01821178011596203),
point(51.492886897176504, 0.05523204803466797),
point(51.49393044412136, 0.06663135252892971),
point(51.498216362670064, 0.0074849557131528854))));
getDs().save(london);
getDs().ensureIndexes();

// when
List<Regions> regionsInTheUK = getDs().find(Regions.class)
.field("regions")
.intersects(lineString(point(37.4056048, -5.9666089),
point(37.404497, -5.9640557)))
.asList();

// then
assertThat(regionsInTheUK.size(), is(1));
assertThat(regionsInTheUK.get(0), is(sevilla));
}

@Test
public void shouldFindGeometryCollectionsWhereTheGivenPointIntersectsWithOneOfTheEntities() {
checkMinServerVersion(2.6);
// given
AllTheThings sevilla = new AllTheThings("Spain", geometryCollection(
multiPoint(point(37.40759155713022, -5.964911067858338),
point(37.40341208875179, -5.9643941558897495),
point(37.40297396667302, -5.970452763140202)),
polygon(point(37.40759155713022, -5.964911067858338),
point(37.40341208875179, -5.9643941558897495),
point(37.40297396667302, -5.970452763140202),
point(37.40759155713022, -5.964911067858338)),
polygon(point(37.38744598813355, -6.001141928136349),
point(37.385990973562, -6.002588979899883),
point(37.386126928031445, -6.002463921904564),
point(37.38744598813355, -6.001141928136349))));
getDs().save(sevilla);

// insert something that's not a geocollection
Regions usa = new Regions("US", multiPolygon(polygon(point(40.75981395319104, -73.98302106186748),
point(40.7636824529618, -73.98049869574606),
point(40.76962974853814, -73.97964206524193),
point(40.75981395319104, -73.98302106186748)),
polygon(point(28.326568258926272, -81.60542246885598),
point(28.327541397884488, -81.6022228449583),
point(28.32950334995985, -81.60564735531807),
point(28.326568258926272, -81.60542246885598))));
getDs().save(usa);

AllTheThings london = new AllTheThings("London", geometryCollection(
point(53.4722454, -2.2235922),
lineString(point(51.507780365645885, -0.21786745637655258),
point(51.50802478194237, -0.21474729292094707),
point(51.5086863655597, -0.20895397290587425)),
polygon(point(51.498216362670064, 0.0074849557131528854),
point(51.49176875129342, 0.01821178011596203),
point(51.492886897176504, 0.05523204803466797),
point(51.49393044412136, 0.06663135252892971),
point(51.498216362670064, 0.0074849557131528854))));
getDs().save(london);
getDs().ensureIndexes();

// when
List<AllTheThings> everythingInTheUK = getDs().find(AllTheThings.class)
.field("everything")
.intersects(lineString(point(37.4056048, -5.9666089),
point(37.404497, -5.9640557)))
.asList();

// then
assertThat(everythingInTheUK.size(), is(1));
assertThat(everythingInTheUK.get(0), is(sevilla));
}

}
Loading

0 comments on commit d5cc107

Please sign in to comment.