在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();
设置正确,你将没有问题。