用于mongo地理位置数据的Meteor简单模式

时间:2014-06-30 14:22:13

标签: mongodb meteor schema

我想为我的meteor app创建一个管理表单;在尝试从头构建一个之前我打算尝试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管理员可以使用它,还是我必须编写自定义管理员的东西?我可能更容易在其他地方构建管理站点,并为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!
  */
  ...
});

3 个答案:

答案 0 :(得分:10)

嗯,我完全不知道保存地铁的过程的解决方案。但是如果你想保存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的标识符。为什么不想为数据添加前缀?

答案 1 :(得分:6)

我的解决方案就像是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知道索引类型。

答案 2 :(得分:2)

OP现在可能已经解决了这个问题,我仍然希望发布我的回答,以回馈StackOverflow社区。

首先,按如下方式创建foreach ($custom_terms as $term) { if ($term->count != 0) { print_r($term->name); } }

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