После того, как вы смоделировали схему, вы можете ссылаться на нее, используя «ref»
var subConfigsSchema = new Schema({
alias: String,
value: String,
position: Number
}, {_id: false});
var subConfigs = mongoose.model('SubConfig', subConfigsSchema);
var configsSchema = new Schema({
bfq: [subConfigsSchema],
qpa: [subConfigsSchema],
fmb: [subConfigsSchema],
cz: [subConfigsSchema]
}, {_id: false});
var config = mongoose.model('Config', ConfigsSchema);
var instrumentSchema = new Schema({
_id: {
type: Schema.Types.ObjectId,
ref: 'SubConfig',
required: true,
auto: true
},
configs: {
type: Schema.Types.ObjectId,
ref: 'Config',
required: true
}
},
{
strict: false,
versionKey: false
});
module.exports = mongoose.model('Instrument', instrumentSchema)
. Теперь при запросе вам нужно заполнить ссылочную модель ... Так что для этого вам нужно заполнить ссылочную модель. [113 ]
Instrument.find({}).populate('subconfig').populate('config').exec((err, data)=> {
if (err) throw err;
instrument = data[0];
console.log(instrument);
console.log(instrument._id);
console.log(instrument.inpname);
console.log(Instrument['inpname']);
});
Если Ваша цель состоит в том, чтобы занять место (сравнивают) расстояния, то приближения (sin
и cos
поиск по таблице), мог решительно уменьшить Ваше количество требуемых вычислений (реализуйте быстрое отклонение.)
Ваша цель состоит в том, чтобы только возобновить фактическое тригонометрическое вычисление, если различие между приближенными расстояниями (чтобы быть оцененным или сравненным) падает ниже определенного порога.
Например, использование справочных таблиц с 1 000 образцов (т.е. sin
и cos
выбранный каждый 2*pi/1000
), неуверенность поиска самое большее 0.006284. Используя вычисление неуверенности для параметра к ACos
, накопленная неуверенность, также быть пороговой неуверенностью, будет самое большее 0.018731.
Так, при оценке Math.Sin(lat2rad) * Math.Sin(lat1rad) + Math.Cos(lat2rad) * Math.Cos(lat1rad) * Math.Cos(lon2rad - lon1rad)
использование sin
и cos
справочные таблицы для двух установленных на координату пар (расстояния) приводят к определенному рейтингу (одно расстояние кажется больше, чем другой на основе приближения), и модуль различия больше, чем порог выше, затем приближение допустимо. Иначе возобновите фактическое тригонометрическое вычисление.
Используя вдохновение от @Brann я думаю, что можно уменьшить вычисление немного (Предупреждение, что это - долгое время, так как я сделал любое из этого, и это должно будет быть проверено). Своего рода поиск предрасчетных значений, вероятно, самое быстрое, хотя
Вы имеете:
1: ACOS (ГРЕШАТ ГРЕХ B + COS COS B COS (A-B)),
но 2: COS (A-B) = ГРЕШИТ ГРЕХ B + COS COS B
который переписывается как 3: ГРЕШИТЕ ГРЕХ B = COS (A-B) - COS COS B
замените ГРЕХ ГРЕХ B в 1. Вы имеете:
4: ACOS (COS (A-B) - COS COS B + COS COS B COS (A-B))
Вы предварительно вычисляете X = COS (A-B) и Y = COS COS B, и Вы помещаете значения в 4
дать:
ACOS (X - Y + XY)
4 аккуратных вычисления вместо 6!
Алгоритм CORDIC работал бы на Вас (в отношении скорости/точности)?
Переключение на справочные таблицы для sin/cos/acos. Будет быстрее, существует много c/c ++ библиотеки фиксированной точки, которые также включают их.
Вот код от кого-то еще на Memoization. Который мог бы работать, если используемые фактические значения более кластеризируются.
Вот ТАК вопрос на Фиксированной точке.
Измените способ, которым Вы храните long/lat:
struct LongLat
{
float
long,
lat,
x,y,z;
}
При создании long/lat также вычислите (x, y, z) 3D точка, которая представляет эквивалентную позицию по сфере единицы, центрируемой в источнике.
Теперь, чтобы определить, ближе ли точка B для указания, чем точка C, сделайте следующее:
// is B nearer to A than C?
bool IsNearer (LongLat A, LongLat B, LongLat C)
{
return (A.x * B.x + A.y * B.y + A.z * B.z) < (A.x * C.x + A.y * C.y + A.z * C.z);
}
и получить расстояние между двумя точками:
float Distance (LongLat A, LongLat B)
{
// radius is the size of sphere your mapping long/lats onto
return radius * acos (A.x * B.x + A.y * B.y + A.z * B.z);
}
Вы могли удалить термин 'радиуса', эффективно нормализовав расстояния.
Как точный Вам нужны значения, чтобы быть?
Если Вы вокруг Ваших значений немного затем Вы могли бы сохранить результат всех поисков и проверить, использовались ли thay перед каждым вычислением?
Каково горлышко бутылки? Вызовы синуса/косинусной функции или вызов arcsine?
Если Ваши вызовы синуса/косинуса являются медленными, Вы могли бы использовать следующую теорему для предотвращения такого количества вызовов:
1 = sin(x)^2 + cos(x)^2
cos(x) = sqrt(1 - sin(x)^2)
Но мне нравится отображающаяся идея так, чтобы Вы не повторно вычисляли значения, которые Вы уже вычислили. Хотя быть осторожным, поскольку карта могла стать очень большой очень быстро.
Я утверждал бы, что можно хотеть вновь исследовать, как Вы нашли что функция быть узким местом. (IE Вы представляли приложение?)
Уравнение мне кажется очень легким весом и не должно доставлять неприятности. Предоставленный, я не знаю Ваше приложение, и Вы говорите, что делаете много этих вычислений.
Тем не менее, это - что-то для рассмотрения.
Ну, так как lat и lon, как гарантируют, будут в определенном диапазоне, Вы могли попытаться использовать некоторую форму справочной таблицы для Вас Математика.* вызовы метода. Скажите, a Dictionary<double,double>
Как кто-то еще указал, действительно ли Вы уверены, что это - Ваше узкое место?
Я сделал некоторое тестирование производительности подобного приложения, которое я создаю, где я называю простой метод возвратить расстояние между двумя точками с помощью аккуратного стандарта. 20 000 вызовов к нему пихают его прямо во главе вывода профилирования, все же нет никакого способа, которым я могу сделать его быстрее... Это - просто сдвиг # вызовов.
В этом случае я должен уменьшить вызовы # до него... Не то, чтобы это - узкое место.
кто-то уже упомянул memoisation, и это немного подобно. если Вы сравнивающий ту же точку со многими другими точками затем лучше предварительно вычислить части того уравнения.
вместо
double result = Math.Acos(Math.Sin(lat2rad) * Math.Sin(lat1rad) + Math.Cos(lat2rad) * Math.Cos(lat1rad) * Math.Cos(lon2rad - lon1rad));
имейте:
double result = Math.Acos(lat2rad.sin * lat1rad.sin + lat2rad.cos * lat1rad.cos * (lon2rad.cos * lon1rad.cos + lon1rad.sin * lon2rad.sin));
и я думаю, что это - та же формула, как кто-то еще отправил, потому что часть уравнения исчезнет при расширении скобок:)
Я использую другой алгоритм для вычисления расстояния между 2 lati/longi положениями, это могло быть легче, чем Ваш, так как это только делает 1 вызов Cos и 1 вызов Sqrt.
public static double GetDistanceBetweenTwoPos(double lat1, double long1, double lat2, double long2)
{
double distance = 0;
double x = 0;
double y = 0;
x = 69.1 * (lat1 - lat2);
y = 69.1 * (long1 - long2) * System.Math.Cos(lat2 / 57.3);
//calculation base : Miles
distance = System.Math.Sqrt(x * x + y * y);
//Distance calculated in Kilometres
return distance * 1.609;
}