#mongodb #meteor #schema
#mongodb #meteor #схема
Вопрос:
Я хочу создать форму администратора для своего приложения meteor; Я собирался попробовать 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 работать с этим, или мне придется писать пользовательские данные администратора? Возможно, мне было бы проще создать сайт администратора в чем-то другом и заставить его выводить данные JSON для Meteor.
Обновление с возможным кодом схемы
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!
*/
...
});
Комментарии:
1. Да, простая схема работает с координатами местоположения. Есть ли у вас какие-либо усилия? Я не знаю администратора Ogno, но в документах написано, что они проверяют с помощью simple-schema, поэтому он должен работать с простой схемой.
2. Я просто не уверен, как форматировать местоположение — особенно массив координат — я не хочу добавлять к данным префиксы «lng» и «lat», а простая схема не имеет типа «Массив» (только строка, число, логическое значение и объект)
3. Простая схема имеет тип массива.
[object]
Перейдите сюда ( github.com/aldeed/meteor-simple-schema ) и выполните поиск «Для указания наличия массива».
Ответ №1:
Хм, я точно не знаю, как решить ваш процесс сохранения географических координат. Но если вы хотите сохранить lng и lat, вам нужно передать префикс. Почему? Ну, геокорды имеют разные диапазоны проверки. Широта доступна только от -90 до 90, а долгота от -180 до 180. Если вы не сохраните префикс, как вы хотите убедиться, какая из координат какая? Еще один совет, который я когда-нибудь сделал false, — сохранить координаты в порядке долготы и широты.
Схема, которую я использую, выглядит следующим образом:
GeocoordsSchema = new SimpleSchema({
lng: {
type : Number,
decimal: true,
min: -180,
max: 180
},
lat: {
type : Number,
decimal: true,
min: -90,
max: 90
}
});
Теперь вы создаете вложенные схемы. Просто расширьте GeocoordsSchema с помощью LocationSchema и добавьте атрибут.
LocationSchema = new SimpleSchema({
type : {
type : String,
autoValue: function() {
return "Point";
}
},
coordinate: {
type: GeocoordsSchema
}
});
Если вы хотите иметь массив LocationSchema, вы можете заключить схему в скобки [].
BeachesSchema = new SimpleSchema({
loc: {
type: [LocationSchema]
}
});
Я не тестировал, но именно так я создаю и внедряю разные схемы. Ну, для этого решения нужен идентификатор lat и lng. Почему вы не хотите указывать префикс своих данных?
Комментарии:
1. Это здорово, большое спасибо chaosborne. Я не думал, что хочу добавлять префикс к своим координатам latlng, потому что моя текущая рабочая схема (возможно, ошибочно) основана на поиске $ near, описанном в документах mongo, но ваш код выглядит действительно хорошо, поэтому сегодня утром я попробую изменить свои данные, чтобы посмотреть, смогу ли я заставить его работать таким образом!
2. Это выглядит как отличный ответ — даст ему шанс.
3. Протестировано и, похоже, не работает с индексом 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. Координаты ограничены с помощью minCount
и maxCount
, хотя я мог бы также использовать другую строку в пользовательской функции проверки. Что-то вроде этого:
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 знал о типе индекса.
Комментарии:
1. Потрясающе, спасибо, что поделились этим! Следует ли переключать индексы lat и lon, поскольку Mongo говорит: «Всегда сохраняйте координаты в порядке долготы и широты».?
2. Спасибо! Вы правы, это была опечатка в сообщении проверки. Исправлено. 🙂
3. Также необходимо переключиться на то, чтобы сначала указать lon в custom: validations, чтобы 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"});