Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Implement $minDistance query operator and geoNear option #171

Merged
merged 1 commit into from

1 participant

@jmikola
Owner

The included documentation link does not yet exist, but it should after https://jira.mongodb.org/browse/DOCS-3112 is resolved.

Closes #169.

@jmikola jmikola Implement $minDistance query operator and geoNear option
The included documentation link does not yet exist, but it should after https://jira.mongodb.org/browse/DOCS-3112 is resolved.

Closes #169.
2b4f78b
@jmikola jmikola merged commit d23af82 into master
@jmikola jmikola deleted the mindistance-option branch
@jmikola jmikola added this to the 1.2.0 milestone
@jmikola jmikola added the feature label
This was referenced
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 10, 2014
  1. @jmikola

    Implement $minDistance query operator and geoNear option

    jmikola authored
    The included documentation link does not yet exist, but it should after https://jira.mongodb.org/browse/DOCS-3112 is resolved.
    
    Closes #169.
This page is out of date. Refresh to see the latest.
View
36 lib/Doctrine/MongoDB/Query/Builder.php
@@ -421,9 +421,9 @@ public function geoIntersects($geometry)
*
* This method sets the "near" option for the geoNear command. The "num"
* option may be set using {@link Expr::limit()}. The "distanceMultiplier",
- * "maxDistance", and "spherical" options may be set using their respective
- * builder methods. Additional query criteria will be assigned to the
- * "query" option.
+ * "maxDistance", "minDistance", and "spherical" options may be set using
+ * their respective builder methods. Additional query criteria will be
+ * assigned to the "query" option.
*
* @see http://docs.mongodb.org/manual/reference/command/geoNear/
* @param float|array|Point $x
@@ -873,6 +873,36 @@ public function maxDistance($maxDistance)
}
/**
+ * Set the "minDistance" option for a geoNear command query or add
+ * $minDistance criteria to the query.
+ *
+ * If the query is a geoNear command ({@link Expr::geoNear()} was called),
+ * the "minDistance" command option will be set; otherwise, $minDistance
+ * will be added to the current expression.
+ *
+ * If the query uses GeoJSON points, $minDistance will be interpreted in
+ * meters. If legacy point coordinates are used, $minDistance will be
+ * interpreted in radians.
+ *
+ * @see Expr::minDistance()
+ * @see http://docs.mongodb.org/manual/reference/command/geoNear/
+ * @see http://docs.mongodb.org/manual/reference/operator/minDistance/
+ * @see http://docs.mongodb.org/manual/reference/operator/near/
+ * @see http://docs.mongodb.org/manual/reference/operator/nearSphere/
+ * @param float $minDistance
+ * @return self
+ */
+ public function minDistance($minDistance)
+ {
+ if ($this->query['type'] === Query::TYPE_GEO_NEAR) {
+ $this->query['geoNear']['options']['minDistance'] = $minDistance;
+ } else {
+ $this->expr->minDistance($minDistance);
+ }
+ return $this;
+ }
+
+ /**
* Specify $mod criteria for the current field.
*
* @see Expr::mod()
View
37 lib/Doctrine/MongoDB/Query/Expr.php
@@ -537,6 +537,43 @@ public function maxDistance($maxDistance)
}
/**
+ * Set the $minDistance option for $near or $nearSphere criteria.
+ *
+ * This method must be called after near() or nearSphere(), since placement
+ * of the $minDistance option depends on whether a GeoJSON point or legacy
+ * coordinates were provided for $near/$nearSphere.
+ *
+ * @see http://docs.mongodb.org/manual/reference/operator/minDistance/
+ * @param float $minDistance
+ * @return self
+ * @throws BadMethodCallException if the query does not already have $near or $nearSphere criteria
+ */
+ public function minDistance($minDistance)
+ {
+ if ($this->currentField) {
+ $query = &$this->query[$this->currentField];
+ } else {
+ $query = &$this->query;
+ }
+
+ if ( ! isset($query['$near']) && ! isset($query['$nearSphere'])) {
+ throw new BadMethodCallException(
+ 'This method requires a $near or $nearSphere operator (call near() or nearSphere() first)'
+ );
+ }
+
+ if (isset($query['$near']['$geometry'])) {
+ $query['$near']['$minDistance'] = $minDistance;
+ } elseif (isset($query['$nearSphere']['$geometry'])) {
+ $query['$nearSphere']['$minDistance'] = $minDistance;
+ } else {
+ $query['$minDistance'] = $minDistance;
+ }
+
+ return $this;
+ }
+
+ /**
* Specify $mod criteria for the current field.
*
* @see Builder::mod()
View
14 tests/Doctrine/MongoDB/Tests/Query/BuilderTest.php
@@ -333,6 +333,7 @@ public function provideProxiedExprMethods()
'type()' => array('type', array(7)),
'all()' => array('all', array(array('value1', 'value2'))),
'maxDistance' => array('maxDistance', array(5)),
+ 'minDistance' => array('minDistance', array(5)),
'mod()' => array('mod', array(2, 0)),
'near()' => array('near', array(1, 2)),
'nearSphere()' => array('nearSphere', array(1, 2)),
@@ -457,6 +458,19 @@ public function testMaxDistanceWithGeoNearCommand()
$this->assertEquals($expected, $qb->debug('geoNear'));
}
+ public function testMinDistanceWithGeoNearCommand()
+ {
+ $expected = array(
+ 'near' => array(0, 0),
+ 'options' => array('spherical' => false, 'minDistance' => 5),
+ );
+
+ $qb = $this->getTestQueryBuilder();
+
+ $this->assertSame($qb, $qb->geoNear(0, 0)->minDistance(5));
+ $this->assertEquals($expected, $qb->debug('geoNear'));
+ }
+
/**
* @expectedException BadMethodCallException
*/
View
50 tests/Doctrine/MongoDB/Tests/Query/ExprTest.php
@@ -113,6 +113,56 @@ public function testMaxDistanceRequiresNearOrNearSphereOperator()
/**
* @dataProvider provideGeoJsonPoint
*/
+ public function testMinDistanceWithNearAndGeoJsonPoint($point, array $expected)
+ {
+ $expr = new Expr();
+ $expr->near($point);
+
+ $this->assertSame($expr, $expr->minDistance(1));
+ $this->assertEquals(array('$near' => $expected + array('$minDistance' => 1)), $expr->getQuery());
+ }
+
+ public function testMinDistanceWithNearAndLegacyCoordinates()
+ {
+ $expr = new Expr();
+ $expr->near(1, 2);
+
+ $this->assertSame($expr, $expr->minDistance(1));
+ $this->assertEquals(array('$near' => array(1, 2), '$minDistance' => 1), $expr->getQuery());
+ }
+
+ public function testMinDistanceWithNearSphereAndGeoJsonPoint()
+ {
+ $json = array('type' => 'Point', 'coordinates' => array(1, 2));
+
+ $expr = new Expr();
+ $expr->nearSphere($this->getMockPoint($json));
+
+ $this->assertSame($expr, $expr->minDistance(1));
+ $this->assertEquals(array('$nearSphere' => array('$geometry' => $json, '$minDistance' => 1)), $expr->getQuery());
+ }
+
+ public function testMinDistanceWithNearSphereAndLegacyCoordinates()
+ {
+ $expr = new Expr();
+ $expr->nearSphere(1, 2);
+
+ $this->assertSame($expr, $expr->minDistance(1));
+ $this->assertEquals(array('$nearSphere' => array(1, 2), '$minDistance' => 1), $expr->getQuery());
+ }
+
+ /**
+ * @expectedException BadMethodCallException
+ */
+ public function testMinDistanceRequiresNearOrNearSphereOperator()
+ {
+ $expr = new Expr();
+ $expr->minDistance(1);
+ }
+
+ /**
+ * @dataProvider provideGeoJsonPoint
+ */
public function testNearWithGeoJsonPoint($point, array $expected)
{
$expr = new Expr();
Something went wrong with that request. Please try again.