【问题标题】:Meteor simple schema for mongo geo location datamongo 地理位置数据的流星简单模式
【发布时间】:2014-08-20 22:55:06
【问题描述】:

我想为我的流星应用创建一个管理表单;在从头开始构建一个之前,我打算尝试 Ogno Admin,但我不确定它是否可以支持我需要的格式的数据。我当前的应用数据像这样进入 mongo:

Beaches.insert({
    "name": "Entry name",
    /* location stored like this so I can use mongo $near queries */
    "location": {
        "type": "Point",
        "coordinates": [-5.0990296,50.110757]
    },
    /* could be many images, minimum 1 */
    "images": [
        {
            "url": "image1.jpg",
            "caption": "Image caption"
        }
    ],
    "shortDesc": "A delightful description...",
    /* fixed list of attributes stored as objects */
    "attributes": {
        "attr 1": {
            "score": 2,
            "text": "attr1 text"
        },

我可以编写一个简单的模式来支持上面的不同数组/对象(尤其是位置坐标)吗?它们必须是方括号格式的 [lng, lat] - ogno admin 可以使用它,还是我必须编写自定义管理内容?对我来说,用其他方式构建管理站点并让它为 Meteor 输出 JSON 数据可能会更容易。

使用可能的架构代码更新

Beaches = new SimpleSchema({
  name: {
    type: String,
  },
  location: {
    type: [Object]
  },
    location.$.type: {
    /* how do I force '"type" : "Point" into every entry?
       use 'autovalue' with the .clean() function?*/
    },
      location.$.coordinates: {
      /* how do I ensure a [x,y] array in here? */
    },
  images: {
    type: [Object]
  },
    "images.$.url": {
        type: String
    },
    "images.$.caption": {
        type: String
    },
  attributes: {
    type: [Object]
  },
  /* note that my attributes above are all prefixed with a 'name'
     eg. "attr 1" : {}
     I'm not sure how to declare these either!
  */
  ...
});

【问题讨论】:

  • 是的,简单模式适用于位置坐标。你有什么努力吗?我不知道 Ogno 管理员,但在文档中写道,他们使用简单模式进行验证,因此它应该使用简单模式。
  • 我只是不确定如何格式化位置——尤其是坐标数组——我不想在数据前加上“lng”和“lat”,而简单模式没有;没有一个“数组”类型(仅限字符串、数字、布尔值和对象)
  • 简单模式确实有一个数组类型。 [object] 到这里 (github.com/aldeed/meteor-simple-schema) 并搜索“指示存在数组”

标签: mongodb meteor schema


【解决方案1】:

嗯,我不确切知道您保存地理坐标的过程的解决方案。但是如果你想保存 lng 和 lat 你必须传递一个前缀。为什么?井地理坐标有不同的验证范围。纬度只能从 -90 到 90,经度只能从 -180 到 180。如果不保存前缀,如何确定哪个是哪个坐标?我有一天做错的另一个提示是以经度、纬度顺序存储坐标。

我使用的架构如下所示:

GeocoordsSchema = new SimpleSchema({
  lng: {
    type : Number,
    decimal: true,
    min: -180,
    max: 180
  }, 
  lat: {
    type : Number,
    decimal: true,
    min: -90,
    max: 90
  }
});

现在您创建嵌套模式。只需使用 LocationSchema 扩展 GeocoordsSchema 并添加一个属性。

LocationSchema = new SimpleSchema({
  type : {
    type : String,
    autoValue: function() {
      return "Point";
    }
  },
  coordinate: {
    type: GeocoordsSchema 
  }
});

如果您想要一个 LocationSchema 数组,则可以将架构包装在 [] 括号中。

BeachesSchema = new SimpleSchema({
  loc: {
    type: [LocationSchema]
  }
});

我还没有测试过,但这就是我创建和嵌套不同模式的方式。那么这个解决方案需要一个 lat 和 lng 的标识符。为什么不想为数据添加前缀?

【讨论】:

  • 这太好了,非常感谢混乱。我不认为我想为我的 latlng 坐标添加前缀,因为我当前的工作模式(可能是错误的)基于 mongo 文档中概述的 $near 搜索 - 但您的代码看起来非常好,所以我将尝试更改我的数据今天早上看看我能不能让它这样工作!
  • 这看起来是一个很好的答案 - 会试一试。
  • 经过测试,似乎不适用于 2ds 索引。简单的 GeocoordsSchema 是一个对象,而不是一个数字数组。
【解决方案2】:

我的解决方案类似于 Chaosbohne,但我通过单个子模式和一些自定义验证来定义整个位置,如下所示:

SimpleSchema.messages
  lonOutOfRange: '[label] longitude should be between -90 and 90'
  latOutOfRange: '[label] latitude should be between -180 and 180'

LocationSchema = new SimpleSchema
  type:
    type: String,
    allowedValues: ['Point']
  coordinates:
    type: [Number]
    decimal: true
    minCount: 2
    maxCount: 2
    custom: ->
      return "lonOutOfRange" unless -90 <= @value[0] <= 90
      return "latOutOfRange" unless -180 < @value[1] <= 180

如果可能,我会使用 SimpleSchema 的现有验证功能。坐标通过minCountmaxCount 进行限制,尽管我也可以在自定义验证函数中使用另一行。像这样的:

SimpleSchema.messages
  needsLatLong: '[label] should be of form [longitude, latitude]'
  lonOutOfRange: '[label] longitude should be between -90 and 90'
  latOutOfRange: '[label] latitude should be between -180 and 180'

LocationSchema = new SimpleSchema
  type:
    type: String,
    allowedValues: ['Point']
  coordinates:
    type: [Number]
    decimal: true
    custom: ->
      return "needsLatLong" unless @value.length is 2
      return "lonOutOfRange" unless -90 <= @value[0] <= 90
      return "latOutOfRange" unless -180 < @value[1] <= 180

现在在你的例子中你会写:

Beaches = new SimpleSchema
  name:
    type: String
  location:
    type: LocationSchema
    index: '2dsphere'
  images:
    type: [Object]
  "images.$.url":
    type: String
  "images.$.caption":
    type: String
  attributes:
    type: [Object]

注意index: '2dsphere',以便 MongoDB 知道索引类型。

【讨论】:

  • 太棒了,谢谢分享!是否应该切换 lat 和 lon 的索引,因为 Mongo 说“始终按经度、纬度顺序存储坐标。”?
  • 谢谢!你是对的,那是验证消息中的一个错字。固定的。 :)
  • 还需要在custom:validations中切换把lon放在首位,这样lonOutOfRange会检查@value[0],对吧?
【解决方案3】:

OP 现在可能已经解决了这个问题,但我仍然想发布我的答案以回馈 StackOverflow 社区的一些爱。

首先,创建一个PlaceSchema,如下:

LocationSchema = new SimpleSchema({
    "type":{
        type: String,
        allowedValues: ["Point"]
    },
    "coordinates":{
        type: Array,
        minCount: 2,
        maxCount: 2
    },
    "coordinates.$":{
        type: Number,
        decimal: true,
        custom: function(){
            if(!(-90 <= this.value[0] <= 90))
                return "lonOutOfRange" ;
            if(!(-180 <= this.value[1] <= 180))
                return "latOutOfRange" ;
        }

    },
    "name": {
        type: String,
        optional: true
    },
});



LocationSchema.messages = {
  lonOutOfRange: 'Longitude out of range', // Must be between -90 and 90
  latOutOfRange: 'Latitude out of range' // Must be between -180 and 180
}

现在在你的主架构中使用它:

BeachSchema = new SimpleSchema({
    name: {
        type: String,
    },
    location: {
        type: LocationSchema // HERE
    }
    // ...
});

然后将架构附加到您的集合中:

Beaches.attachSchema(BeachSchema);//*/

您也可以考虑通过以下方式添加2dsphere 索引:

Beaches._ensureIndex({ "location": "2dsphere"});

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-14
    • 1970-01-01
    • 1970-01-01
    • 2017-04-05
    • 2017-01-04
    相关资源
    最近更新 更多