根据特定点的坐标和最大距离查找与某个点的最近点 - 使用带有 MEAN 堆栈的 Mongoose 未定义查询结果 [英] Finding Closest Points to a certain Point Given its Coordinates and Maximum Distance - Query Result Undefined using Mongoose with MEAN Stack

查看:20
本文介绍了根据特定点的坐标和最大距离查找与某个点的最近点 - 使用带有 MEAN 堆栈的 Mongoose 未定义查询结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题在几天之内都无法解决,即使查看了相关的 Stack Overflow Q/A.

我正在开发一个重复使用

给定图像,我想要这样,例如,如果我插入 2000(公里),我的查询将找到距离 P0 最大 2000 公里的所有点.在这个例子中,它可能应该给我 P1 和 P2.

当我的 Mongoose Schema 中只有 Points 时,我能够做到这一点.

我有这个只有标记(点)的Schema:

//拉取 Mongoose 依赖来创建模式var mongoose = require('mongoose');var Schema = mongoose.Schema;//创建一个用户架构.var MarkerSchema = 新架构({用户名:{类型:字符串,必填:真},location: {type: [Number], required: true},//[Long, Lat]created_at: {type: Date, default: Date.now},更新时间:{类型:日期,默认:Date.now}});//以 2dsphere 格式索引此架构MarkerSchema.index({location: '2dsphere'});module.exports = mongoose.model('mean-markers', MarkerSchema);

这是我的仅用于标记的旧查询:

var User = require('./model.js');app.post('/query/', function(req, res) {//从正文中获取所有查询参数.var lat = req.body.latitude;var long = req.body.longitude;var 距离 = req.body.distance;var reqVerified = req.body.reqVerified;//打开一个通用的 Mongoose 查询var query = User.find({});//...包括最大距离过滤器(将英里转换为米)如果(距离){//使用MongoDB的地理空间查询功能query = query.where('location').near({中央: {类型:'点',坐标:[长,纬度]},//将米转换为英里最大距离:距离 * 1609.34,球形:真实});}});

效果非常好,我能够获得接近点.

然后,我将我的 Schema 更改为更加动态,并且还支持 Polylines 和 Polygons.

我可以使用以下 Schema 插入和绘制新的点、折线和多边形:

var mongoose = require('mongoose');var GeoJSON = require('geojson');var Schema = mongoose.Schema;//创建一个位置架构.var LocationSchema = 新架构({名称:{类型:字符串,必填:真},地点: {类型:{类型:字符串,需要:真},坐标:[Schema.Types.Mixed]},created_at: {type: Date, default: Date.now},更新时间:{类型:日期,默认:Date.now}});LocationSchema.index({location: '2dsphere'});module.exports = mongoose.model('mean-locations', LocationSchema);

这是我的Mongoose Query:

var GeoObjects = require('./model.js');app.post('/query/', function(req, res) {//从正文中获取所有查询参数.var lat = req.body.latitude;var long = req.body.longitude;var 距离 = req.body.distance;无功查询;如果(距离){查询 = GeoObjects.find({'location.type':'Point'}).where('location.coordinates').near({中央: {类型:'点',坐标:[纬度,经度]},//将米转换为英里最大距离:距离 * 1609.34,球形:真实});}//执行查询并返回查询结果query.exec(function(err, users) {如果(错误)res.send(err);控制台日志(用户);//如果没有错误,响应所有符合条件的用户的 JSONres.json(用户);});});

console.log(users); 给我 undefined.

在我的 queryCtrl.js 中记录查询结果给了我以下错误消息:

name: "MongoError", message: "error processing query: ns=MeanMapApp.mean-locatio…ed error: cannot find index for $geoNear query", waitedMS: 0, ok: 0, errmsg:错误处理查询:ns=MeanMapApp.mean-locatio…ed 错误:无法找到 $geoNear 查询的索引"

相同但略有不同:

app.post('/query/', function(req, res) {//从正文中获取所有查询参数.var lat = req.body.latitude;var long = req.body.longitude;var 距离 = req.body.distance;console.log(lat,long,distance);var points = GeoObjects.find({'location.type':'Point'});var loc = parseFloat(points.location.coordinates);console.log(JSON.stringify(loc));如果(距离){var query = points.near(loc, {中央: {类型:'点',坐标:[parseFloat(lat), parseFloat(long)]},//将米转换为英里最大距离:距离 * 1609.34,球形:真实});}});

这是一个标记示例:

<代码>{"name": "user01",地点": {"类型":"点",坐标":[102.0, 0.0]}}

$near 运算符如何处理距离和 maxDistance:

来自 Scotch 使用 Google 地图制作 MEAN 应用程序(部分II) 作者:艾哈迈德·哈克

<块引用>

MongoDB 搜索参数 $near 及其相关属性maxDistance 和spherical 来指定我们要覆盖的范围.我们将查询正文的距离乘以 1609.34,因为我们希望获取用户的输入(以英里为单位)并将其转换为MongoDB 期望的单位(以米为单位).

  1. 为什么我得到 undefined?
  2. 这个问题可能是由我的架构引起的吗?
  3. 我该如何解决这个问题?

如果您想收到一些说明,请在下方发表评论.

提前致谢.

解决方案

我终于设法解决了这个问题.

本质上,问题是由架构引起的,因为 2dIndex 被引用到错误的字段 (类型和坐标).

我使用以下架构解决了:

var mongoose = require('mongoose');var GeoJSON = require('geojson');var Schema = mongoose.Schema;var geoObjects = 新架构({名称:{类型:字符串},类型: {类型:字符串,枚举:[观点","线串",多边形"]},坐标:[数字],created_at: {type: Date, default: Date.now},更新时间:{类型:日期,默认:Date.now}});//设置 created_at 参数等于当前时间geoObjects.pre('save', function(next){现在 = 新日期();this.updated_at = 现在;如果(!this.created_at){this.created_at = 现在}下一个();});geoObjects.index({坐标:'2dsphere'});module.exports = mongoose.model('geoObjects', geoObjects);

以及以下查询:

app.post('/query/', function(req, res) {//从正文中获取所有查询参数.var lat = req.body.latitude;var long = req.body.longitude;var 距离 = req.body.distance;var query = GeoObjects.find({'type':'Point'});//...包括最大距离过滤器如果(距离){//使用 MongoDB 的地理空间查询功能.query = query.where('坐标').near({中央: {类型:'点',坐标:[纬度,经度]},//将米转换为英里最大距离:距离 * 1609.34,球形:真实});}//执行查询并返回查询结果query.exec(function(err, geoObjects) {如果(错误)res.send(err);//如果没有错误,用 JSON 响应res.json(geoObjects);});});

希望对大家有所帮助!

编辑

我放置的模式导致 LineStringsPolygons 出现一些问题.

这里是允许使用 geoQueries

的正确模式

linestring-model.js:

var mongoose = require('mongoose');var Schema = mongoose.Schema;//创建一个 LineString 架构.var linestrings = new Schema({名称:{类型:字符串,必需:真},地理:{类型:{类型:字符串,默认值:LineString"},坐标:数组},created_at: {type: Date, default: Date.now},更新时间:{类型:日期,默认:Date.now}});//设置 created_at 参数等于当前时间linestrings.pre('save', function(next){现在 = 新日期();this.updated_at = 现在;如果(!this.created_at){this.created_at = 现在}下一个();});linestrings.index({geo: '2dsphere'});module.exports = mongoose.model('linestrings', linestrings);

polygon-model.js

var mongoose = require('mongoose');var Schema = mongoose.Schema;//创建一个多边形架构.var 多边形 = 新架构({名称:{类型:字符串,必需:真},地理:{类型:{类型:字符串,默认值:多边形"},坐标:数组},created_at: {type: Date, default: Date.now},更新时间:{类型:日期,默认:Date.now}});//设置 created_at 参数等于当前时间多边形.pre('保存',函数(下一个){现在 = 新日期();this.updated_at = 现在;如果(!this.created_at){this.created_at = 现在}下一个();});多边形索引({地理:'2dsphere'});module.exports = mongoose.model('polygons', 多边形);

LineString 插入:

<代码>{"name" : "myLinestring",地理":{"type" : "LineString",坐标":[[17.811,12.634],[12.039,18.962],[15.039,18.962],[29.039,18.962]]}}

多边形插入:

<代码>{"name" : "保利",地理":{类型":多边形",坐标":[[[25.774, -80.190], [18.466, -66.118],[32.321, -64.757], [25.774, -80.190]]]}}

I've an issue that I wasn't able to solve in some days, even looking at related Stack Overflow Q/A.

I'm developing an application reusing Scotch's Create a MEAN Stack Google Map App Tutorial by Ahmed Haque approach.

I'm trying to implement an application that uses Google Maps API to draw Points, LineStrings and Polygons which coordinates are contained in GeoJson files that are stored in a MongoDB instance.

I'm using Mongoose to build the Schema for my data and query my MongoDB database.

I would like to find the closest Points CP to a certain Points P0 given P0's latitude and longitude and given a maximum radius distance used to find the interested points.

Given the image over, I would like that, for example, if I insert 2000 (kilometers), my query will find all the points maximum 2000 kilometers away from P0. In this example, it should probably give me P1 and P2.

I was able to do it when I only had Points in my Mongoose Schema.

I had this Schema with only markers (Points):

// Pulls Mongoose dependency for creating schemas
var mongoose    = require('mongoose');
var Schema      = mongoose.Schema;

// Creates a User Schema. 
var MarkerSchema = new Schema({
    username: {type: String, required: true},
    location: {type: [Number], required: true}, // [Long, Lat]
    created_at: {type: Date, default: Date.now},
    updated_at: {type: Date, default: Date.now}
});

// Indexes this schema in 2dsphere format
MarkerSchema.index({location: '2dsphere'});

module.exports = mongoose.model('mean-markers', MarkerSchema);

And this was my Old Query for only Markers:

var User = require('./model.js');

app.post('/query/', function(req, res) {

        // Grab all of the query parameters from the body.
        var lat = req.body.latitude;
        var long = req.body.longitude;
        var distance = req.body.distance;
        var reqVerified = req.body.reqVerified;

        // Opens a generic Mongoose Query
        var query = User.find({});

        // ...include filter by Max Distance (converting miles to meters)
        if (distance) {

            // Using MongoDB's geospatial querying features
            query = query.where('location').near({
                center: {
                    type: 'Point',
                    coordinates: [long, lat]
                },

                // Converting meters to miles
                maxDistance: distance * 1609.34,
                spherical: true
            });
        }
});

It worked really well, and I was able to get close points.

Then, I changed my Schema to be more dynamic and also support Polylines and Polygons.

I'm able to insert and draw new Points, Polylines and Polygons with the following Schema:

var mongoose = require('mongoose');
var GeoJSON  = require('geojson');
var Schema   = mongoose.Schema;

// Creates a Location Schema.
var LocationSchema = new Schema({
                                    name: {type: String, required: true},
                                    location: {
                                      type: {type : String, required: true},
                                      coordinates : [Schema.Types.Mixed]
                                    },
                                    created_at: {type: Date, default: Date.now},
                                    updated_at: {type: Date, default: Date.now}
});

LocationSchema.index({location: '2dsphere'});
module.exports = mongoose.model('mean-locations', LocationSchema);

And this is my Mongoose Query:

var GeoObjects = require('./model.js');

app.post('/query/', function(req, res) {

    // Grab all of the query parameters from the body.
    var lat = req.body.latitude;
    var long = req.body.longitude;
    var distance = req.body.distance;

    var query;

    if (distance) {
        query = GeoObjects.find({'location.type':'Point'})
                    .where('location.coordinates').near({
                      center: {
                        type: 'Point',
                        coordinates: [lat, long]
                      },
                      // Converting meters to miles
                      maxDistance: distance * 1609.34,
                      spherical: true
        });
    }

    // Execute Query and Return the Query Results
    query.exec(function(err, users) {
        if (err)
            res.send(err);
        console.log(users);
        // If no errors, respond with a JSON of all users that meet the criteria
        res.json(users);
    });
});

console.log(users); gives me undefined.

Logging query results in my queryCtrl.js gives me the following error message:

name: "MongoError", message: "error processing query: ns=MeanMapApp.mean-locatio…ed error: unable to find index for $geoNear query", waitedMS: 0, ok: 0, errmsg: "error processing query: ns=MeanMapApp.mean-locatio…ed error: unable to find index for $geoNear query"

Same with a little variation:

app.post('/query/', function(req, res) {

    // Grab all of the query parameters from the body.
    var lat = req.body.latitude;
    var long = req.body.longitude;
    var distance = req.body.distance;

    console.log(lat,long,distance);

    var points = GeoObjects.find({'location.type':'Point'});

    var loc = parseFloat(points.location.coordinates);
    console.log(JSON.stringify(loc));

    if (distance) {
        var query = points.near(loc, {
                      center: {
                        type: 'Point',
                        coordinates: [parseFloat(lat), parseFloat(long)]
                      },
                      // Converting meters to miles
                      maxDistance: distance * 1609.34,
                      spherical: true
        });
    }
});

This is an example of a marker:

{
  "name": "user01",
  "location": {
                "type":"Point",
                "coordinates": [102.0, 0.0]

  }
}

How $near operator works with distance and maxDistance:

From Scotch's Making MEAN Apps with Google Maps (Part II) by Ahmed Haque

MongoDB search parameter $near and its associated properties maxDistance and spherical to specify the range we’re looking to cover. We’re multiplying the distance of our query body by 1609.34, because we want to take our users’ input (in miles) and convert it into the units MongoDB expects (in meters).

  1. Why Am I getting undefined?
  2. Is it possible that this problem is caused by my Schema?
  3. How can I fix this?

If you would like to receive some clarifications just post a comment below.

Thanks in Advance.

解决方案

I finally managed to solve this issue.

Essentially, the issue was caused by the schema, since 2dIndex was referred to a wrong field (type and coordinates).

I solved using the following Schema:

var mongoose = require('mongoose');
var GeoJSON  = require('geojson');
var Schema   = mongoose.Schema;

var geoObjects = new Schema({
                               name : {type: String},
                               type: {
                                       type: String,
                                       enum: [
                                               "Point",
                                               "LineString",
                                               "Polygon"
                                             ]
                                      },
                                coordinates: [Number],
                                created_at: {type: Date, default: Date.now},
                                updated_at: {type: Date, default: Date.now}
});

// Sets the created_at parameter equal to the current time
geoObjects.pre('save', function(next){
   now = new Date();
   this.updated_at = now;
   if(!this.created_at) {
      this.created_at = now
   }
   next();
});

geoObjects.index({coordinates: '2dsphere'});

module.exports = mongoose.model('geoObjects', geoObjects);

And the following Query:

app.post('/query/', function(req, res) {

        // Grab all of the query parameters from the body.
        var lat = req.body.latitude;
        var long = req.body.longitude;
        var distance = req.body.distance;

        var query = GeoObjects.find({'type':'Point'});

        // ...include filter by Max Distance 
        if (distance) {

            // Using MongoDB's geospatial querying features. 
            query = query.where('coordinates').near({
                center: {
                    type: 'Point',
                    coordinates: [lat, long]
                },

                // Converting meters to miles
                maxDistance: distance * 1609.34,
                spherical: true
            });
        }

        // Execute Query and Return the Query Results
        query.exec(function(err, geoObjects) {
            if (err)
                res.send(err);

            // If no errors, respond with a JSON 
            res.json(geoObjects);
        });
    });

I hope it will help someone!

EDIT

The schema I put over causes a bit of problems with LineStrings and Polygons.

Here are correct schemas which allow using geoQueries

linestring-model.js:

var mongoose = require('mongoose');
var Schema   = mongoose.Schema;

// Creates a LineString Schema.
var linestrings = new Schema({
    name: {type: String, required : true},
    geo : {
        type : {type: String,
            default: "LineString"},
        coordinates : Array
    },
    created_at: {type: Date, default: Date.now},
    updated_at: {type: Date, default: Date.now}
});

// Sets the created_at parameter equal to the current time
linestrings.pre('save', function(next){
    now = new Date();
    this.updated_at = now;
    if(!this.created_at) {
        this.created_at = now
    }
    next();
});

linestrings.index({geo : '2dsphere'});
module.exports = mongoose.model('linestrings', linestrings);

polygon-model.js

var mongoose = require('mongoose');
var Schema   = mongoose.Schema;

// Creates a Polygon Schema.
var polygons = new Schema({
    name: {type: String, required : true},
    geo : {
        type : {type: String,
            default: "Polygon"},
        coordinates : Array
    },
    created_at: {type: Date, default: Date.now},
    updated_at: {type: Date, default: Date.now}
});

// Sets the created_at parameter equal to the current time
polygons.pre('save', function(next){
    now = new Date();
    this.updated_at = now;
    if(!this.created_at) {
        this.created_at = now
    }
    next();
});

polygons.index({geo : '2dsphere'});
module.exports = mongoose.model('polygons', polygons);

LineString Insert:

{  
    "name" : "myLinestring", 
    "geo" : {
        "type" : "LineString", 
        "coordinates" : [
            [
                17.811, 
                12.634
            ], 
            [
                12.039, 
                18.962
            ], 
            [
                15.039, 
                18.962
            ], 
            [
                29.039, 
                18.962
            ]
        ]
    }
}

Polygon Insert:

{  
    "name" : "Poly", 
    "geo" : {
        "type" : "Polygon", 
        "coordinates" :  [
                           [ 
                             [25.774, -80.190], [18.466, -66.118], 
                             [32.321, -64.757], [25.774, -80.190] 
                           ]
                         ]
    }
}

这篇关于根据特定点的坐标和最大距离查找与某个点的最近点 - 使用带有 MEAN 堆栈的 Mongoose 未定义查询结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆