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

brgchamk  于 2023-08-06  发布在  Go
关注(0)|答案(3)|浏览(91)

我试图在我的用户模型中保存一个位置的经度/纬度,并使用$geoNear查询它。我几乎看过了我能找到的关于这个主题的所有页面,但我仍然不确定如何1)适当地创建模型以及如何查询它。
这是我的模型的一部分:

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

字符串
@1:根据文档,如果我想存储点,类型必须是'Point',但它会抛出

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()时不可用)
到目前为止,我所做的一切都毫无进展,所以我现在的问题是:

  • 我 Mongoose 模型应该是什么样子?
  • 如何在数据库中存储用户及其位置

任何帮助将不胜感激!

qmelpv7a

qmelpv7a1#

如果你想让一个schema支持GeoJSON,你首先需要正确地构造它:

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

字符串
这可以确保不与模式定义的“type”关键字混淆。如果你真的想支持所有的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地理空间查询表单支持的经度然后纬度顺序。
接下来,不要直接在原始驱动程序方法上深入研究数据库命令的模糊用法,而是使用直接支持的东西,这样更好。例如.aggregate()方法的$geoNear

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


把事情安排好,你就不会有问题了。

unftdfkk

unftdfkk2#

这对我来说是点和多边形的更好的解决方案。

var WeSchema = new Schema({
Location: {
    type: {
      type: String,
      enum: ['Point', 'Polygon']
    },
    coordinates: [Number] 
  }
});
WeSchema.index({Location: '2dsphere' });

字符串

xdyibdwo

xdyibdwo3#

我面临以下错误:

ApolloError: geoNear command failed: { ok: 0.0, errmsg: "no geo indices for geoNear" }

字符串
代码:

const mongoose = require("mongoose");

mongoose.Promise = global.Promise;

const ToDoSchema = new mongoose.Schema(
  {
    title: { type: String, required: true },
    gmap: { geoJson: { type: { type: String }, coordinates: [Number] } },
  },
  { timestamps: true }
);
ToDoSchema.index({ "gmap.geoJson": "2dsphere" });

export default mongoose.models.things_to_do ||
  mongoose.model("things_to_do", ToDoSchema, "things_to_do");

相关问题