在Mongoose中使用带有地理空间坐标的find()(NodeJS + MongoDB)

时间:2021-09-24 02:35:22

Mongoose version: 3.6 Node version: 0.10

Mongoose版本:3.6节点版本:0.10

I have been trying to solve this problem for hours. I want to find all the documents closer than maxDistance to some coordinates. I am trying to use the GeoJSON specifications of MongoDB (2dsphere), so that I can input the distance in meters.

我一直试图解决这个问题几个小时。我想找到比maxDistance更接近某些坐标的所有文档。我正在尝试使用MongoDB(2dsphere)的GeoJSON规范,这样我就可以输入以米为单位的距离。

This is my schema "venue.js":

这是我的架构“venue.js”:

var db = require('mongoose'),
    Schema = db.Schema,
    ObjectId = Schema.ObjectId;

var venueSchema = new Schema({
    geo: { type: [Number], index: '2dsphere'},
    city: String,
    name: String,
    address: String
});


module.exports = db.model('Venue', venueSchema);

This is where I insert the query ctrlVenue.js:

这是我插入查询ctrlVenue.js的地方:

var Venue = require('../models/venue.js');


VenueController = function(){};

/** GET venues list ordered by the distance from a "geo" parameter. Endpoint: /venues
    Params:
        - geo: center for the list of venues - longitude, latitude (default: 25.466667,65.016667 - Oulu);
        - maxDistance: maxímum distance from the center for the list of venues (default: 0.09)
**/
exports.getVenues =function(req, res) {

    var maxDistance = typeof req.params.maxDistance !== 'undefined' ? req.params.maxDistance : 0.09; //TODO: validate
    var geo  =  typeof req.params.geo !== 'undefined' ? req.params.geo.split(',') : new Array(25.466667, 65.016667); //TODO: validate

    var lonLat = { $geometry :  { type : "Point" , coordinates : geo } };


    Venue.find({ geo: {
        $near: lonLat,
        $maxDistance: maxDistance
    }}).exec(function(err,venues){
        if (err)
            res.send(500, 'Error #101: '+err);
        else 
            res.send(venues);
        }); 
    }

When I run the code I receive the error:

当我运行代码时,我收到错误:

"Error #101: CastError: Cast to number failed for value \"[object Object]\" at path \"geo\""

“错误#101:CastError:对于路径\”geo \“中的值\”[object Object] \“,转换为数字失败

If I instead modify this line:

如果我改为修改此行:

$near: lonLat,

with

$near: geo,

I correctly get the documents, but then, I cannot use meters as unit of measure. I based my assumptions on the following table: http://docs.mongodb.org/manual/reference/operator/query-geospatial/

我正确地得到了文件,但是,我不能用米作为计量单位。我的假设基于下表:http://docs.mongodb.org/manual/reference/operator/query-geospatial/

I have seen plenty of functioning examples using $geometry but none together with $near. What am I doing wrong?

我已经看到很多使用$ geometry的功能示例,但没有使用$ near。我究竟做错了什么?

1 个解决方案

#1


3  

I had to use the Mixed type and added some custom validation to ensure values were arrays and had a length of 2. I also checked for empty arrays and converted them to nulls because this is required when using sparse indices with 2dsphere. (Mongoose helpfully sets array fields to [] for you, which is not a valid coordinate!)

我不得不使用Mixed类型并添加了一些自定义验证以确保值是数组并且长度为2.我还检查了空数组并将它们转换为空值,因为在使用2dsphere的稀疏索引时需要这样做。 (Mongoose帮助你为[]设置数组字段,这不是一个有效的坐标!)

var schema = new mongoose.Schema({
  location: { type: {}, index: '2dsphere', sparse: true }
});

schema.pre('save', function (next) {
  var value = that.get('location');

  if (value === null) return next();
  if (value === undefined) return next();
  if (!Array.isArray(value)) return next(new Error('Coordinates must be an array'));
  if (value.length === 0) return that.set(path, undefined);
  if (value.length !== 2) return next(new Error('Coordinates should be of length 2'))

  next();
});

#1


3  

I had to use the Mixed type and added some custom validation to ensure values were arrays and had a length of 2. I also checked for empty arrays and converted them to nulls because this is required when using sparse indices with 2dsphere. (Mongoose helpfully sets array fields to [] for you, which is not a valid coordinate!)

我不得不使用Mixed类型并添加了一些自定义验证以确保值是数组并且长度为2.我还检查了空数组并将它们转换为空值,因为在使用2dsphere的稀疏索引时需要这样做。 (Mongoose帮助你为[]设置数组字段,这不是一个有效的坐标!)

var schema = new mongoose.Schema({
  location: { type: {}, index: '2dsphere', sparse: true }
});

schema.pre('save', function (next) {
  var value = that.get('location');

  if (value === null) return next();
  if (value === undefined) return next();
  if (!Array.isArray(value)) return next(new Error('Coordinates must be an array'));
  if (value.length === 0) return that.set(path, undefined);
  if (value.length !== 2) return next(new Error('Coordinates should be of length 2'))

  next();
});