Skip to content
This repository

Support GeoJSON and 2dsphere queries #109

Merged
merged 16 commits into from about 1 year ago

3 participants

Jeremy Mikola Patrik Karisch SteveTalbot
Jeremy Mikola
Owner
jmikola commented

This PR:

Todo items:

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

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.

Jeremy Mikola
Owner

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.

Jeremy Mikola
Owner

@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).

Jeremy Mikola
Owner

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

patkar and others added some commits
Patrik Karisch patkar add $geoIntersects criteria with box geometry bfe6d10
Patrik Karisch patkar GeoJSON format expects a number b411e69
Patrik Karisch patkar added test for geointersect with box 195dd89
Patrik Karisch patkar changed function parameters to x/y pairs as in other geospatial funct…
…ions
e1a3bfe
Patrik Karisch patkar add $geoWithin for GeoJSON polygon 23c40e2
Patrik Karisch patkar Add $geoIntersects with all three GeoJSON types and a box helper aa8ff32
Patrik Karisch patkar Add box helper for $geoWithin a1dcfee
Jeremy Mikola jmikola Support GeoJSON polygons (with holes)
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.
53fd3b1
Jeremy Mikola jmikola Update param type docs for older geo builder methods 298c888
Jeremy Mikola jmikola Rename Query::TYPE_GEO_LOCATION to TYPE_GEO_NEAR 9d0dde0
Jeremy Mikola jmikola Separate unit and functional query builder tests ef52acb
Jeremy Mikola jmikola Use GeoJson objects for 2dsphere query builder/expr methods
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.
f8cb37d
Jeremy Mikola jmikola Unit tests for all Builder methods that simply proxy Expr methods f1c59ef
Jeremy Mikola jmikola Support GeoJSON geometry arrays in addition to the library objects
This relaxes the GeoJSON library dependency, so 2dsphere queries (namely $geoIntersects and $geoWithin) can still be done without it.
04e7acb
Jeremy Mikola jmikola Support GeoJSON points for geoNear collection method 6e5624d
Jeremy Mikola jmikola Remove superfluous array from GeoJSON point fixture c430f0e
Jeremy Mikola jmikola merged commit edcacb1 into from
Jeremy Mikola jmikola closed this
Jeremy Mikola jmikola deleted the branch
Jeremy Mikola jmikola referenced this pull request in doctrine/mongodb-odm
Open

Support GeoJSON and 2dsphere queries #631

1 of 3 tasks complete
SteveTalbot

Hi Jeremy,

The same change needs to be made in doctrine/mongodb-odm. Details here: doctrine/mongodb-odm#643

Guess this is an easy one for you to fix?

Cheers,
Steve

Owner

@SteveTalbot: See my reply in doctrine/mongodb-odm#643. Thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Showing 16 unique commits by 2 authors.

Jul 11, 2013
Patrik Karisch patkar add $geoIntersects criteria with box geometry bfe6d10
Patrik Karisch patkar GeoJSON format expects a number b411e69
Patrik Karisch patkar added test for geointersect with box 195dd89
Patrik Karisch patkar changed function parameters to x/y pairs as in other geospatial funct…
…ions
e1a3bfe
Patrik Karisch patkar add $geoWithin for GeoJSON polygon 23c40e2
Patrik Karisch patkar Add $geoIntersects with all three GeoJSON types and a box helper aa8ff32
Patrik Karisch patkar Add box helper for $geoWithin a1dcfee
Jeremy Mikola jmikola Support GeoJSON polygons (with holes)
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.
53fd3b1
Jeremy Mikola jmikola Update param type docs for older geo builder methods 298c888
Jeremy Mikola jmikola Rename Query::TYPE_GEO_LOCATION to TYPE_GEO_NEAR 9d0dde0
Jeremy Mikola jmikola Separate unit and functional query builder tests ef52acb
Jeremy Mikola jmikola Use GeoJson objects for 2dsphere query builder/expr methods
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.
f8cb37d
Jeremy Mikola jmikola Unit tests for all Builder methods that simply proxy Expr methods f1c59ef
Jeremy Mikola jmikola Support GeoJSON geometry arrays in addition to the library objects
This relaxes the GeoJSON library dependency, so 2dsphere queries (namely $geoIntersects and $geoWithin) can still be done without it.
04e7acb
Jeremy Mikola jmikola Support GeoJSON points for geoNear collection method 6e5624d
Jeremy Mikola jmikola Remove superfluous array from GeoJSON point fixture c430f0e
Something went wrong with that request. Please try again.