【问题标题】: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() 时不可用)

到目前为止,我所做的一切都没有成功,所以我现在的问题是:

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

任何帮助将不胜感激!

【问题讨论】:

    标签: node.js mongodb mongoose mongodb-query geospatial


    【解决方案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。
      猜你喜欢
      • 1970-01-01
      • 2018-08-19
      • 1970-01-01
      • 2015-03-23
      • 2021-04-07
      • 2018-08-04
      • 2021-10-24
      • 2020-09-12
      • 2017-04-06
      相关资源
      最近更新 更多