Uploaded image for project: 'Core Server'
  1. Core Server
  2. SERVER-24440

Points near the poles may fail to be returned by $nearSphere with 2d index

    XMLWordPrintable

    Details

    • Operating System:
      ALL
    • Steps To Reproduce:
      Hide

      Apply the following patch and run python buildscripts/resmoke.py --executor=no_passthrough jstests/noPassthrough/geo_full.js.

      diff --git a/jstests/noPassthrough/geo_full.js b/jstests/noPassthrough/geo_full.js
      index 4912292..44ca81c 100644
      --- a/jstests/noPassthrough/geo_full.js
      +++ b/jstests/noPassthrough/geo_full.js
      @@ -24,8 +24,8 @@ db = testServer.getDB("test");
       
       var randEnvironment = function() {
       
      -    // Normal earth environment
      -    if (Random.rand() < 0.5) {
      +    // Always use the normal earth environment for simplicity.
      +    if (Random.rand() < 0.5 || true) {
               return {
                   max: 180,
                   min: -180,
      @@ -55,7 +55,8 @@ var randPoint = function(env, query) {
               return query.exact;
       
           if (env.earth)
      -        return [Random.rand() * 360 - 180, Random.rand() * 180 - 90];
      +        // Generate points at any longitude in [-180, 180) and only latitudes in [89, 90).
      +        return [Random.rand() * 360 - 180, 90 - Random.rand()];
       
           var range = env.max - env.min;
           return [Random.rand() * range + env.min, Random.rand() * range + env.min];
      

      Show
      Apply the following patch and run python buildscripts/resmoke.py --executor=no_passthrough jstests/noPassthrough/geo_full.js . diff --git a/jstests/noPassthrough/geo_full.js b/jstests/noPassthrough/geo_full.js index 4912292..44ca81c 100644 --- a/jstests/noPassthrough/geo_full.js +++ b/jstests/noPassthrough/geo_full.js @@ -24,8 +24,8 @@ db = testServer.getDB("test"); var randEnvironment = function() { - // Normal earth environment - if (Random.rand() < 0.5) { + // Always use the normal earth environment for simplicity. + if (Random.rand() < 0.5 || true) { return { max: 180, min: -180, @@ -55,7 +55,8 @@ var randPoint = function(env, query) { return query.exact; if (env.earth) - return [Random.rand() * 360 - 180, Random.rand() * 180 - 90]; + // Generate points at any longitude in [-180, 180) and only latitudes in [89, 90). + return [Random.rand() * 360 - 180, 90 - Random.rand()]; var range = env.max - env.min; return [Random.rand() * range + env.min, Random.rand() * range + env.min];
    • Linked BF Score:
      0

      Description

      The GeoNear2DStage has its own implementation for projecting a spherical region to a flat annulus. Siyuan Zhou and I read through the code and suspect the issue is with the computeXScanDistance() function, but aren't clear on the details (read: math) that cause $nearSphere queries to omit points from the flat annulus that were included in the spherical region.

      inline double computeXScanDistance(double y, double maxDistDegrees) {
          // TODO: this overestimates for large maxDistDegrees far from the equator
          return maxDistDegrees / std::min(cos(deg2rad(std::min(+89.0, y + maxDistDegrees))),
                                           cos(deg2rad(std::max(-89.0, y - maxDistDegrees))));
      }
      

      As a workaround, one can perform the $nearSphere queries with a "2dsphere" index to get the expected results.


      Note: This is a separate issue from the one reported in SERVER-21594, as the $maxDistance specified in to the $nearSphere query doesn't necessarily cause it to cross over the pole.

      Additionally, $geoWithin queries that use $centerSphere don't appear to be affected by this issue because they use the S2 library to perform the projection from the spherical region to the flat box.

        Attachments

          Issue Links

            Activity

              People

              • Votes:
                0 Vote for this issue
                Watchers:
                6 Start watching this issue

                Dates

                • Created:
                  Updated: