在猫鼬中创建和查找地理位置
Posted
技术标签:
【中文标题】在猫鼬中创建和查找地理位置【英文标题】:Create & Find GeoLocation in mongoose 【发布时间】:2015-11-18 21:37:44 【问题描述】:我正在尝试将某个位置的经度/纬度保存在我的用户模型中,并使用$geoNear
进行查询。我几乎查看了我能找到的关于该主题的所有页面,但我仍然不确定如何 1) 适当地创建模型以及如何查询它。
这是我模型的一部分:
loc:
//type: 'Point', // see 1
//type: String, // see 2
coordinates: [Number],
index: '2dsphere' // see 3
,
@1:根据文档,如果我想存储一个点,类型必须是“点”,但它会抛出
TypeError: Undefined type `Point` at `loc`
Did you try nesting Schemas? You can only nest using refs or arrays.
这是有道理的,因为我猜应该是String
@2:这不会立即引发错误,但是当我尝试存储用户时,我得到:
name: 'ValidationError',
errors:
loc:
[CastError: Cast to String failed for value "[object Object]" at path "loc"]
@3:如果我想创建这样的索引,我会收到错误:
TypeError: Undefined type `2dsphere` at `loc.index`
Did you try nesting Schemas? You can only nest using refs or arrays.
所以我尝试将索引存储到对我来说更合适的位置,如下所示:
userSchema.index('loc': '2dsphere');
当我尝试保存新用户时会引发以下错误:
- [MongoError: Can't extract geo keys from object, malformed geometry?: coordinates: [ -73.97, 40.77 ] ]
name: 'MongoError',
message: 'Can\'t extract geo keys from object, malformed geometry?: coordinates: [ -73.97, 40.77 ] ',
ok: 1,
n: 0,
code: 16572,
errmsg: 'Can\'t extract geo keys from object, malformed geometry?: coordinates: [ -73.97, 40.77 ] ',
writeConcernError:
code: 16572,
errmsg: 'Can\'t extract geo keys from object, malformed geometry?: coordinates: [ -73.97, 40.77 ] '
MongoError: Can't extract geo keys from object, malformed geometry?: coordinates: [ -73.97, 40.77 ]
当我将数据库上的模型更新为 $geoNear
命令时,我像这样更新了我的用户:
loc: coordinates: [-73.97, 40.77]
并且可以像这样成功查询它:
mongoose.model('users').db.db.command(
"geoNear": users,
"near": [
<latitude>,
<longitude>
],
"spherical": true,
"distanceMultiplier": 6378.1, // multiplier for kilometres
"maxDistance": 100 / 6378.1, // every user within 100 km
"query":
(我使用了 db.command,因为从我读到的 $geoNear
在使用 find()
时不可用)
到目前为止,我所做的一切都没有成功,所以我现在的问题是:
我的猫鼬模型应该是什么样子? 如何在我的数据库中存储用户及其位置任何帮助将不胜感激!
【问题讨论】:
【参考方案1】:这对我来说是点和多边形的更好解决方案。
var WeSchema = new Schema(
Location:
type:
type: String,
enum: ['Point', 'Polygon']
,
coordinates: [Number]
);
WeSchema.index(Location: '2dsphere' );
【讨论】:
【参考方案2】:如果您希望架构支持 GeoJSON,您首先需要正确构建它:
var userSchema = new Schema(
loc:
type: type: String ,
coordinates: [Number],
);
这确保不会与架构定义的“类型”关键字混淆。如果你真的想支持所有的 GeoJSON 类型,那么你可以稍微宽松一点:
var userSchema = new Schema(
loc:
type: type: String ,
coordinates: []
);
接下来你想将索引绑定到 shema:
userSchema.index( "loc": "2dsphere" );
然后当然定义一个模型并正确存储东西:
var User = mongoose.model( "User", userSchema );
var user = new User(
"loc":
"type": "Point",
"coordinates": [-73.97, 40.77]
);
请注意,您的数据必须按照 GeoJSON 和所有 MongoDB 地理空间查询表单支持的 longitude 然后 latitude 顺序。
接下来,与其直接在原始驱动程序方法上深入研究数据库命令的晦涩用法,不如使用直接支持的东西,这样会更好。如$geoNear
为.aggregate()
方法:
User.aggregate(
[
"$geoNear":
"near":
"type": "Point",
"coordinates": [<long>,<lat>]
,
"distanceField": "distance",
"spherical": true,
"maxDistance": 10000
],
function(err,results)
)
现在因为数据是 GeoJSON,距离已经转换成米,所以不需要做其他转换工作。
另请注意,您一直在搞砸这个,除非您删除集合,否则您尝试过的任何索引仍然存在,这可能会导致问题。
您可以轻松地从 mongodb shell 中的集合中删除所有索引:
db.users.dropIndexes();
或者,由于您可能需要对数据进行一些重新整形,然后删除集合并重新开始:
db.users.drop();
正确设置,您不会有任何问题。
【讨论】:
感谢您的帮助!用户的存储现在可以正常工作。我还会看看你的aggregate
实现,看起来比我以前的那种 hack 好得多
感谢您提供此信息,请在您的地理查询中使用 "spherical"
而不是 "sperical"
。
@ColoGhidini 你能解释一下吗:(为什么聚合更好)“Next, rather than dig into obscure usages of database commands directly on the raw driver method, use things instead that are directly supported, and better
”
这个方法已经不行了。即使将索引添加到架构中,它也会返回以下错误:$geoNear requires a 2d or 2dsphere index。以上是关于在猫鼬中创建和查找地理位置的主要内容,如果未能解决你的问题,请参考以下文章