Browse Source

DATAMONGO-1134 - Add support for $geoIntersects.

We now support $geoIntersects via Criteria.intersects(…) using GeoJSON types.

Original pull request: #295.
pull/299/merge
Christoph Strobl 11 years ago committed by Oliver Gierke
parent
commit
ee04c014c9
  1. 12
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java
  2. 26
      spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java
  3. 15
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java
  4. 40
      spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java

12
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java

@ -222,7 +222,7 @@ public class QueryMapper { @@ -222,7 +222,7 @@ public class QueryMapper {
protected DBObject getMappedKeyword(Keyword keyword, MongoPersistentEntity<?> entity) {
// $or/$nor
if (keyword.isOrOrNor() || keyword.hasIterableValue()) {
if (keyword.isOrOrNor() || (keyword.hasIterableValue() && !keyword.isGeometry())) {
Iterable<?> conditions = keyword.getValue();
BasicDBList newConditions = new BasicDBList();
@ -552,6 +552,16 @@ public class QueryMapper { @@ -552,6 +552,16 @@ public class QueryMapper {
return key.matches(N_OR_PATTERN);
}
/**
* Returns whether the current keyword is the {@code $geometry} keyword.
*
* @return
* @since 1.8
*/
public boolean isGeometry() {
return "$geometry".equalsIgnoreCase(key);
}
public boolean hasIterableValue() {
return value instanceof Iterable;
}

26
spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java

@ -190,8 +190,8 @@ public class Criteria implements CriteriaDefinition { @@ -190,8 +190,8 @@ public class Criteria implements CriteriaDefinition {
*/
public Criteria in(Object... o) {
if (o.length > 1 && o[1] instanceof Collection) {
throw new InvalidMongoDbApiUsageException("You can only pass in one argument of type "
+ o[1].getClass().getName());
throw new InvalidMongoDbApiUsageException(
"You can only pass in one argument of type " + o[1].getClass().getName());
}
criteria.put("$in", Arrays.asList(o));
return this;
@ -433,7 +433,23 @@ public class Criteria implements CriteriaDefinition { @@ -433,7 +433,23 @@ public class Criteria implements CriteriaDefinition {
}
/**
* Creates a geospatical criterion using a {@literal $maxDistance} operation, for use with $near
* Creates criterion using {@code $geoIntersects} operator which matches intersections of the given {@code geoJson}
* structure and the documents one. Requires MongoDB 2.4 or better.
*
* @param geoJson must not be {@literal null}.
* @return
* @since 1.8
*/
@SuppressWarnings("rawtypes")
public Criteria intersects(GeoJson geoJson) {
Assert.notNull(geoJson, "GeoJson must not be null!");
criteria.put("$geoIntersects", geoJson);
return this;
}
/**
* Creates a geo-spatial criterion using a {@literal $maxDistance} operation, for use with $near
*
* @see http://docs.mongodb.org/manual/reference/operator/query/maxDistance/
* @param maxDistance
@ -526,8 +542,8 @@ public class Criteria implements CriteriaDefinition { @@ -526,8 +542,8 @@ public class Criteria implements CriteriaDefinition {
private Criteria registerCriteriaChainElement(Criteria criteria) {
if (lastOperatorWasNot()) {
throw new IllegalArgumentException("operator $not is not allowed around criteria chain element: "
+ criteria.getCriteriaObject());
throw new IllegalArgumentException(
"operator $not is not allowed around criteria chain element: " + criteria.getCriteriaObject());
} else {
criteriaChain.add(criteria);
}

15
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java

@ -775,6 +775,21 @@ public class QueryMapperUnitTests { @@ -775,6 +775,21 @@ public class QueryMapperUnitTests {
assertThat(dbo, isBsonObject().containing("geoJsonPoint.$geoWithin.$geometry.type", "Polygon"));
}
/**
* @see DATAMONGO-1134
*/
@Test
public void intersectsShouldUseGeoJsonRepresentationCorrectly() {
Query query = query(where("geoJsonPoint").intersects(
new GeoJsonPolygon(new Point(0, 0), new Point(100, 100), new Point(100, 0), new Point(0, 0))));
DBObject dbo = mapper.getMappedObject(query.getQueryObject(), context.getPersistentEntity(ClassWithGeoTypes.class));
assertThat(dbo, isBsonObject().containing("geoJsonPoint.$geoIntersects.$geometry.type", "Polygon"));
assertThat(dbo, isBsonObject().containing("geoJsonPoint.$geoIntersects.$geometry.coordinates"));
}
@Document
public class Foo {
@Id private ObjectId id;

40
spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2010-2014 the original author or authors.
* Copyright 2010-2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,12 +17,13 @@ package org.springframework.data.mongodb.core.query; @@ -17,12 +17,13 @@ package org.springframework.data.mongodb.core.query;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.Assert.*;
import static org.springframework.data.mongodb.test.util.IsBsonObject.*;
import org.junit.Test;
import org.springframework.data.geo.Point;
import org.springframework.data.mongodb.InvalidMongoDbApiUsageException;
import org.springframework.data.mongodb.core.geo.GeoJsonLineString;
import org.springframework.data.mongodb.core.geo.GeoJsonPoint;
import org.springframework.data.mongodb.test.util.IsBsonObject;
import com.mongodb.BasicDBObject;
import com.mongodb.BasicDBObjectBuilder;
@ -176,7 +177,7 @@ public class CriteriaTests { @@ -176,7 +177,7 @@ public class CriteriaTests {
DBObject dbo = new Criteria("foo").near(new GeoJsonPoint(100, 200)).getCriteriaObject();
assertThat(dbo, IsBsonObject.isBsonObject().containing("foo.$near.$geometry", new GeoJsonPoint(100, 200)));
assertThat(dbo, isBsonObject().containing("foo.$near.$geometry", new GeoJsonPoint(100, 200)));
}
/**
@ -187,7 +188,7 @@ public class CriteriaTests { @@ -187,7 +188,7 @@ public class CriteriaTests {
DBObject dbo = new Criteria("foo").near(new Point(100, 200)).getCriteriaObject();
assertThat(dbo, IsBsonObject.isBsonObject().notContaining("foo.$near.$geometry"));
assertThat(dbo, isBsonObject().notContaining("foo.$near.$geometry"));
}
/**
@ -198,7 +199,7 @@ public class CriteriaTests { @@ -198,7 +199,7 @@ public class CriteriaTests {
DBObject dbo = new Criteria("foo").near(new GeoJsonPoint(100, 200)).maxDistance(50D).getCriteriaObject();
assertThat(dbo, IsBsonObject.isBsonObject().containing("foo.$near.$maxDistance", 50D));
assertThat(dbo, isBsonObject().containing("foo.$near.$maxDistance", 50D));
}
/**
@ -209,7 +210,7 @@ public class CriteriaTests { @@ -209,7 +210,7 @@ public class CriteriaTests {
DBObject dbo = new Criteria("foo").nearSphere(new GeoJsonPoint(100, 200)).maxDistance(50D).getCriteriaObject();
assertThat(dbo, IsBsonObject.isBsonObject().containing("foo.$nearSphere.$maxDistance", 50D));
assertThat(dbo, isBsonObject().containing("foo.$nearSphere.$maxDistance", 50D));
}
/**
@ -220,7 +221,7 @@ public class CriteriaTests { @@ -220,7 +221,7 @@ public class CriteriaTests {
DBObject dbo = new Criteria("foo").near(new GeoJsonPoint(100, 200)).minDistance(50D).getCriteriaObject();
assertThat(dbo, IsBsonObject.isBsonObject().containing("foo.$near.$minDistance", 50D));
assertThat(dbo, isBsonObject().containing("foo.$near.$minDistance", 50D));
}
/**
@ -231,7 +232,7 @@ public class CriteriaTests { @@ -231,7 +232,7 @@ public class CriteriaTests {
DBObject dbo = new Criteria("foo").nearSphere(new GeoJsonPoint(100, 200)).minDistance(50D).getCriteriaObject();
assertThat(dbo, IsBsonObject.isBsonObject().containing("foo.$nearSphere.$minDistance", 50D));
assertThat(dbo, isBsonObject().containing("foo.$nearSphere.$minDistance", 50D));
}
/**
@ -243,8 +244,27 @@ public class CriteriaTests { @@ -243,8 +244,27 @@ public class CriteriaTests {
DBObject dbo = new Criteria("foo").nearSphere(new GeoJsonPoint(100, 200)).minDistance(50D).maxDistance(100D)
.getCriteriaObject();
assertThat(dbo, IsBsonObject.isBsonObject().containing("foo.$nearSphere.$minDistance", 50D));
assertThat(dbo, IsBsonObject.isBsonObject().containing("foo.$nearSphere.$maxDistance", 100D));
assertThat(dbo, isBsonObject().containing("foo.$nearSphere.$minDistance", 50D));
assertThat(dbo, isBsonObject().containing("foo.$nearSphere.$maxDistance", 100D));
}
/**
* @see DATAMONGO-1134
*/
@Test(expected = IllegalArgumentException.class)
public void intersectsShouldThrowExceptionWhenCalledWihtNullValue() {
new Criteria("foo").intersects(null);
}
/**
* @see DATAMONGO-1134
*/
@Test
public void intersectsShouldWrapGeoJsonTypeInGeometryCorrectly() {
GeoJsonLineString lineString = new GeoJsonLineString(new Point(0, 0), new Point(10, 10));
DBObject dbo = new Criteria("foo").intersects(lineString).getCriteriaObject();
assertThat(dbo, isBsonObject().containing("foo.$geoIntersects.$geometry", lineString));
}
}

Loading…
Cancel
Save