Skip to content
This repository has been archived by the owner on Nov 11, 2020. It is now read-only.

Support GeoJSON and 2dsphere queries #109

Merged
merged 16 commits into from
Jul 11, 2013
Merged

Support GeoJSON and 2dsphere queries #109

merged 16 commits into from
Jul 11, 2013

Conversation

jmikola
Copy link
Member

@jmikola jmikola commented May 15, 2013

This PR:

Todo items:

  • Ensure $maxDistance works with $near 2dsphere queries
  • Support $centerSphere with $geoWithin
  • Tests for all geospatial operators

@QuingKhaos
Copy link
Contributor

1) $geoWithin and $near

New in version 2.4: $geoWithin replaces $within which is deprecated.

For the most shapes it's a simple copy of the old within* methods and prefix them with geo and change the operator. Except polygons. How to differ if the given coordinates are legacy coordinate pairs or a geojson polygon? With a parameter $legacy? Or with spherical(true)? Or depending on the array depth? Legacy coordinates allowing only one array of coordinate tuples and no inner and outer rings as with a geojson polygon possible.

The same with the $near command.

2) $centerSphere with $geoWithin

The $centerSphere expects the radius in radians. Should the user take care of the calculation or the query builder? For the second I think of a method signature like

public function geoWithinCenterSphere($x, $x, $radius, $multiplier = SomeUtilClass::KILOMETERS)

Simply it does the same as the user can, but if the user forgets about the radius should be in radians, the $radius parameter is assumed to be in kilometers. The constant in the util class (which would fit?) are simple the right multipliers (6378.137 for km and 3963.192 miles), which allows the user to specify a custom multiplier.

@jmikola
Copy link
Member Author

jmikola commented Jul 1, 2013

How to differ if the given coordinates are legacy coordinate pairs or a geojson polygon?

I created a library two weeks ago, geojson, that I'm hoping will address this without the need to create duplicate methods. If the first argument is a Geometry object, we'd immediately know to use the GeoJSON operators under the hood. Additionally, the library does all the validation of shapes upon construction. I blogged about this last week here.

Should the user take care of the calculation or the query builder?

I think this is best left to the user. If the sphere happens to not be earth, the multiplier will differ anyway. Also, this would let Doctrine avoid having to default to accepting miles or kilometers. If the user did want to pass radians, and we defaulted to one of the other units, they'd have to specify a multiplier of 1.

@jmikola
Copy link
Member Author

jmikola commented Jul 2, 2013

@patkar: I resolved the outstanding todo items and pushed the changes I discussed in my last comment. Let me know what you think.

I added deprecation doc tags to the older within*() methods, as $within is deprecated in MongoDB now. Those methods now refer to corresponding geoWithin*() methods, which use the $geoWithin operator. I also removed the new GeoJSON helper methods you created (e.g. intersecting lines, points, polygons). GeoJSON only shows up with the new geoIntersects() and geoWithin() methods, and optionally as the first argument (a point) in near() and nearSphere().

I want to be careful to leave the GeoJSON library as an optional dependency, so perhaps I can go a step further and remove the type-hints in geoIntersects() and geoWithin() and allow the user to send in an array, which will be used as-is. The array will be expected to be a GeoJSON geometry, such as:

[
  'type' => 'Point',
  'coordinates' => [1, 2],
]

If a GeoJSON object is passed in, I can call jsonSerialize() as is currently done in the Expr class. Likewise, we could do this for near() and nearSphere() as well. If their $x argument is an array, I'll expect it to be a GeoJSON point (just like above).

@jmikola
Copy link
Member Author

jmikola commented Jul 2, 2013

87cb4b1 adds support for using basic arrays, removing the dependency on jmikola/geojson for $geoIntersects and $geoWithin queries.

QuingKhaos and others added 16 commits July 11, 2013 14:18
This changes the polygon methods to accept an array of rings, which themselves are arrays of point tuples. Subsequent rings define holes in the first ring (i.e. outer polygon). In the future, it may be worthwhile to have a builder for polygons.
This adds an optional dependency to a GeoJSON library (see: composer.json) for handling 2dsphere queries in query builder and expression methods. It was necessary to discern between GeoJSON points and legacy coordinates for $near and $nearSphere operators, due to how they incorporate the $maxDistance option. Additionally, using an external library for GeoJSON geometries removes the responsibility of validating those geometries from doctrine/mongodb.

Tests were updated and added for all geospatial methods in the builder and expression classes.
This relaxes the GeoJSON library dependency, so 2dsphere queries (namely $geoIntersects and $geoWithin) can still be done without it.
jmikola added a commit that referenced this pull request Jul 11, 2013
Support GeoJSON and 2dsphere queries
@jmikola jmikola merged commit edcacb1 into master Jul 11, 2013
@jmikola jmikola deleted the gh102-2dsphere branch July 11, 2013 19:03
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support 2dsphere queries
3 participants