Mongoose calls to geoNear with GeoJSON points as query parameters not working

流过昼夜 提交于 2019-12-05 02:25:51

问题


Given a schema defined for documents containing a GeoJSON location;


var BranchSchema = new Schema({
  location: {
    'type': {
      type: String,
      required: true,
      enum: ['Point', 'LineString', 'Polygon'],
      default: 'Point'
    },
    coordinates: [Number]
  },
  name: String
});
BranchSchema.index({location: '2dsphere'});

And some sample data:


[
  {
    "name": "A",
    "location": {
      "type": "Point",
      "coordinates": [153.027117, -27.468515 ] //Brisbane, Australia
    }
  },
  {
    "name": "B",
    "location": {
      "type": "Point",
      "coordinates": [153.029884, -27.45643] //Also Brisbane, Australia
    }
  }
]

The following geoNear query is not behaving as expected. I read this query as "given a location off the coast of South America, trawl through the locations and find any that are within 1 meter of the provided location."


// Somewhere off the east coast of South America.
var point = {type: 'Point', coordinates: [0.0776590, -33.7797590]};

Branch.geoNear(point, {maxDistance:1, spherical: true}, function (err, data) {
  ...
  // at this point I expected data.length === 0.
  // Instead it is returning both documents.
  ...
});

What am I doing wrong?

  • I'm using [long,lat] when defining a position as per the WGS84 standard.
  • Runnings MongooseJS V3.8.8

回答1:


The problem was incorrectly using maxDistance. The following expression worked.


Branch.geoNear({type: "Point", coordinates: [0.0776590, -33.7797590]}, {
  spherical: true, 
  maxDistance: 1 / 6378137, 
  distanceMultiplier: 6378137
})
  .then(function (doc) {
    console.log(doc);
    process.exit();
  });


Mongoose: branches.ensureIndex({ location: '2dsphere' }) { safe: undefined, background: true }  
Mongoose: branches.geoNear(0.077659) -33.779759 { distanceMultiplier: 6378137, lean: true, maxDistance: 1.567855942887398e-7, spherical: true } 
[]

Now the query correctly discovers that the two documents in the collection are not within 1 meter of the queried location. Querying a location closer to home also gives us the expected results.


Branch.geoNear({type: "Point", coordinates: [153.027117, -27.468515]}, {
  spherical: true, 
  maxDistance: 1 / 6378137, 
  distanceMultiplier: 6378137
})
  .then(function (doc) {
    console.log(doc);
    process.exit();
  });

Mongoose: branches.ensureIndex({ location: '2dsphere' }) { safe: undefined, background: true }  
Mongoose: branches.geoNear(153.027117) -27.468515 { distanceMultiplier: 6378137, lean: true, maxDistance: 1.567855942887398e-7, spherical: true } 
[ { dis: 0.0026823704060803567,
    obj: 
     { name: 'A',
       _id: 533200e49ba06bec37c0cc22,
       location: [Object],
       __v: 0 } } ]

The solution?

MongoDb documentation of geoNear states that if using a geoJSON object maxDistance should be in meters, and in radians if using coordinate pairs.

Optional. A distance from the center point. Specify the distance in meters for GeoJSON data and in radians for legacy coordinate pairs. MongoDB limits the results to those documents that fall within the specified distance from the center point. http://docs.mongodb.org/manual/reference/command/geoNear/#dbcmd.geoNear

This is either wrong, or my understanding of it is wrong.

As you can see above, rather than specifying 1 meter for maxDistance, it is supplied in Radians.

As at the date of this post geoNear requires that maxDistance be in Radians regardless of whether you are using a geoJSON object or a legacy coordinate pair.




回答2:


Mongoose was converting geoJSON points to legacy coordinate pairs due to a limitation in the native driver; support has been added to the native driver, and there's an open PR to add this support to Mongoose. Ive updated the issue provided by @NickB.



来源:https://stackoverflow.com/questions/22623998/mongoose-calls-to-geonear-with-geojson-points-as-query-parameters-not-working

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!