Комментарии 18
Спасибо, классная статья, тоже люблю Graphopper)
А как на примере Postgres данные по трафику задавать?
Спасибо за отзыв.
Можно поподробнее "трафик", это что? Какой у него аналог в тегах OSM? highway?
Если я правильно понял вопрос, то общий подход такой:
Вы можете создавать в таблице любые поля. Главное добавить их во вьюшку см. Подготовка данных
Затем эти данные можно считывать из БД таким образом см. graphhopper-reader-postgis
for (String tag : tagsToCopy) {
Object val = road.getAttribute(tag);
if (val != null) {
way.setTag(tag, val);
}
}
highway
там вот так обрабатывается:
// Тип дороги
Object type = road.getAttribute("fclass");
if (type != null) {
way.setTag("highway", type.toString());
}
т.е. здесь могут быть любые атрибуты, какие пожелаете.
Encoder обрабатывает этот тег например как в CarFlagEncoder
нет, не совсем, трафик это информация по пробкам, вот есть пример реализации
я так полагаю, данные по трафику так же можно валить в БД и далее учитывать при построении маршрута, например меняя maxspeed (мое предположение)
Пример реализации ещё не смотрел. Интересно как они реализовали, посмотрю обязательно.
Я бы так реализовывал: в БД я бы хранил только редко меняемые или постоянные параметры, информация о пробках меняется динамически, - в БД её хранить не оптимально, - потребует постоянной перезаписи. По крайней мере не в той же базе, которая используется для построителя.
Я бы обработку вынес в класс в связанный с определением веса см. weighting. Уже в момент обработки ребра при маршрутиации смотрел какая на нём нагрузка - возможно получая её из стороннего сервиса, и использовал бы полученные данные для расчёта веса переопределив calcEdgeWeight из
AbstractWeighting
Посмотрел пример. Их задумка оказалась не сложной, всё в классе DataUpdater:
Есть у них какой-то волшебный сервис http://www.stadt-koeln.de/externe-dienste/open-data/traffic.php. Он возвращает загруженность дорог, и с координатами.
Они получают
LocationIndex locationIndex = hopper.getLocationIndex();
и находят в нём рёбра по координатам.В найденном ребре подменяют скорость см. lockedFeed
if (oldSpeed != value) {
updates++;
// TODO use different speed for the different directions (see e.g. Bike2WeightFlagEncoder)
logger.info("Speed change at " + entry.getId() + " (" + point + "). Old: " + oldSpeed + ", new:" + value);
edge.setFlags(carEncoder.setSpeed(edge.getFlags(), value));
}
Этот locationIndex
потом в классе Router применяется.
Но в целом они тоже используют внешний источник для информации по трафику
я только не понимаю, какой speed они меняют, который maxspeed?
Обратите внимание на строки
if (oldSpeed != value) {
updates++;
// TODO use different speed for the different directions (see e.g. Bike2WeightFlagEncoder)
logger.info("Speed change at " + entry.getId() + " (" + point + "). Old: " + oldSpeed + ", new:" + value);
edge.setFlags(carEncoder.setSpeed(edge.getFlags(), value));
}
Они не оперируют такими понятиями как скорость максимальная/минимальная/средняя. Есть просто "скорость", и graphhopper при построении самого быстрого маршрута полагается на неё, это видно из класса FastestWeighting, в методе calcEdgeWeight
.
Понятие maxSpeed
там скорее стоит воспринимать как "максимальная скорость с которой можно ехать превозмогая всё (пробки, качество дорог, сопротивление воздуха) кроме правил дорожного движения".
String sql = String.format("DELETE FROM %s WHERE gid IN (%s)", layerName, StringUtils.join(deletesIds, ','));
Ням-ням. В одном из айдишников может быть значение:
"1);DROP DATABASE;--"
И начнётся развлекательная программа. Где ваш продакшн?
Ээээ. Вы про вот этот метод что ли:
private void deleteFromTemp(List<Long> deletesIds) {
if (!deletesIds.isEmpty()) {
String sql = String.format("DELETE FROM %s WHERE gid IN (%s)", layerName, StringUtils.join(deletesIds, ','));
jdbcTemplate.update(sql);
}
}
Вы уверены что в одном из этих List<Long> deletesIds
айдишников может быть что-то пободное DROP DATABASE ?
Ну ладно, но одумайтесь, сегодня вы превращаете List<Long> в DROP DATABASE
, завтра свинец в золото, а послезавтра сожгут на костре.
Джунам раз за разом объясняют -- конкатенация и форматирование SQL зло, И раз за разом одни и те же SQL инъекции. В одном из примеров инъекцию вы точно прошляпили. Поэтому и спрашиваю про прод -- человеческий язык не все понимают. То ли дело язык упавшего прода
Мы всё про тот же самый пример, в котором вы утверждаете что что среди айдишников может быть DROP DATABASE
?
Если да, то это найденная SQL инъекция основана на аксиоме о том, что в List<Long>
можно написать "1);DROP DATABASE;--".
Боюсь что это не так. Если же действительно можно, то объясните каким образом, а не ходите вокруг да около с "человеческий язык не все понимают", - постараюсь всё-таки понять, для того мы здесь и пишем.
И рассматривать одну строку:
String sql = String.format("DELETE FROM %s WHERE gid IN (%s)", layerName, StringUtils.join(deletesIds, ','));
в отрыве от остального метода - не комильфо.
Мы всё про тот же самый пример, в котором вы утверждаете что что среди айдишников может быть
DROP DATABASE
?
Нет, я бегло проверил другие примеры и нашёл подходящий. Я о том и говорю, что многие люди не понимают языка человеческого. Поэтому начнём с дропнутой БД, а потом плавно перейдём к работе над ошибками
Позвольте вмешаться, про инъекции с вами согласен, но не в этом конкретном примере. У автора метод принимает коллекцию из различных Long и скорее всего в этом случае не найдется никакого long значения = «1);DROP DATABASE;--».
Да, в данном случае согласен. Java не динамический язык -- и тут сюрпризов не будет. Сюрпризы пораждает сам джуновский подход -- и я вижу как раз одно подходящее место в другом запросе. А вообще мне любопытно пощупать, как оно работает
Не хотел Вас расстраивать, но если Вы внимательно посмотрите на сервис в GitHub gist то увидите, что публичные методы принимают либо параметры типа Long
, либо org.postgis.Geometry
, с Long
Вы уже поспешили засунуть туда SQL инъекцию, теперь видимо пытаетесь с Geometry,
ну если вам известен способ как в org.postgis.Geometry
засунуть не пойми что, то соглашусь что инъекция возможна.
Да есть ещё layerName
, но к нему не предусмотрен публичный доступ (см. GitHub gist), перекомпилировать разве что.
В общем, хватит бравировать, все найденные вами инъекции основаны на невнимательности, поспешности и попытке рассмотреть строку в отрыве от метода.
Если хотите пощупать, то ещё раз сообщаю что БД есть в контейнере, а исходный код я ни от кого, так же, не утаиваю - хотите щупайте.
Тем более непонятно, если бы Вы ошибку нашли, то давно бы её озвучили, но Вы продолжаете пускать пыль в глаза, что как бы наводит на мысль, что это блеф, чтобы не выглядеть нелепо после поспешно найденной инъекции.
И теперь вместо того чтобы обсуждать предмет публикации я вынужден реагировать на ваш комплекс учителя.
Как хранить сеть дорог в БД для построения маршрута?