在mongoose中创build和查找地理位置

我试图在我的用户模型中保存位置的经度/纬度,并用$geoNear查询它。 我已经查看了几乎所有可以find该主题的页面,但是我仍然不确定如何1)适当地创build模型以及如何查询它。

这是我的模型的一部分:

 loc: { //type: 'Point', // see 1 //type: String, // see 2 coordinates: [Number], index: '2dsphere' // see 3 }, 

@ 1:根据文档的types必须是'点',如果我想存储一个点,但它会抛出

 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:如果我想创build这样的索引,我得到的错误:

 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()

我到目前为止所尝试的一切都无济于事,现在我的问题是:

  • 我的mongoose模型应该如何?
  • 我如何将用户的位置存储在我的数据库中

任何帮助将非常感激!

如果你想要一个模式来支持GeoJSON,你首先需要正确地构造:

 var userSchema = new Schema({ loc: { type: { type: String }, coordinates: [Number], } }); 

这确保了模式定义的“types”关键字没有混淆。 如果你真的想支持GeoJSONtypes的整个范围,那么你可以稍微松一点:

 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地理空间查询表单所支持的经度和 纬度顺序。

接下来,不要直接在原始驱动程序方法中深入挖掘数据库命令的模糊用法,而是使用直接支持的东西,而且更好。 比如.aggregate()方法的$geoNear

 User.aggregate( [ { "$geoNear": { "near": { "type": "Point", "coordinates": [<long>,<lat>] }, "distanceField": "distance", "spherical": true, "maxDistance": 10000 }} ], function(err,results) { } ) 

而现在因为数据是GeoJSON,距离已经转换成米,所以不需要做其他的转换工作。

另外请注意,你一直在搞这个,除非你删除集合,你试过的任何索引都会在那里,这可能会导致问题。

您可以轻松地将集合中的所有索引放在mongodbshell中:

 db.users.dropIndexes(); 

或者因为您可能需要重新进行一些数据修改,请删除收集并重新开始:

 db.users.drop(); 

设置正确,你将没有问题。