diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java index 82a97e2d5..ef9d8a6cf 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/convert/QueryMapper.java @@ -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 { 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; } diff --git a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java index 8b9ddad87..ae1f227d6 100644 --- a/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java +++ b/spring-data-mongodb/src/main/java/org/springframework/data/mongodb/core/query/Criteria.java @@ -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 { } /** - * 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 { 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); } diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java index c0ef246a9..b510d7145 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/convert/QueryMapperUnitTests.java @@ -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; diff --git a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java index 4244af9d2..dc8e1ce84 100644 --- a/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java +++ b/spring-data-mongodb/src/test/java/org/springframework/data/mongodb/core/query/CriteriaTests.java @@ -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; 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 { 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 { 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 { 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 { 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 { 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 { 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 { 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)); + } }