问题描述
我有一个问题在几天之内都无法解决,即使查看了相关的 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 期望的单位(以米为单位).
- 为什么我得到
undefined
? - 这个问题可能是由我的架构引起的吗?
- 我该如何解决这个问题?
如果您想收到一些说明,请在下方发表评论.
提前致谢.
我终于设法解决了这个问题.
本质上,问题是由架构引起的,因为 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);});});
希望对大家有所帮助!
编辑
我放置的模式导致 LineStrings
和 Polygons
出现一些问题.
这里是允许使用 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.
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
- Why Am I getting
undefined
? - Is it possible that this problem is caused by my Schema?
- 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 未定义查询结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!