Рассчитать расстояние на основе координат - PullRequest
0 голосов
/ 01 июня 2019

Моя задача - рассчитать общую длину дорог от города.Я использую данные OSM.После импорта в базу данных у меня есть следующая структура (мне это показалось логичным, но я могу изменить, если вы думаете, что есть лучший способ):

  • Для каждого сегмента проезда есть корневой узел (метка пути в OSM XML), которая содержит идентификатор и тип (у меня есть и другие типы, но они не имеют значения сейчас)
  • К корневому узлу подключен первый узел дороги с отношением 'определяет'
  • Каждый узел связан со следующим узлом с именем' connected ', у которого есть свойство entity_id, которое является идентификатором корневых узлов.(Один узел может появляться в большем количестве участков дороги, например, на перекрестках, поэтому я стараюсь избегать кругов с этим свойством.

Я довольно новичок в Neo4J. У меня есть только опыт работы с базами данных SQLно, исходя из этого, я чувствую, что даже если бы мой подход работал, он потерял бы преимущество языка запросов (имеется в виду скорость).

Так вот, что я имею до сих пор, но это даже не близкоОн выводит одно и то же число (неправильное число) много раз вместо одного итогового значения. Я почти уверен, что не получил полное представление о с , но не могу понять, каково было бы решение:

CREATE (t:Tmp {total:0})
with t
MATCH (e:Entity {type:'road'})
with collect(e) as es, t
    unwind es as entity
        match p = ()-[r:connected {entity_id:entity.int_id}]->()
        with entity, p,t 
        SET entity.lng = 0
        with entity, p, t
        unwind nodes(p) as nd
            with  t,nd,point({longitude:toFloat(nd.lon), latitude: toFloat(nd.lat)}) as point1, entity
                SET entity.lng = entity.lng + distance(entity.p, point1)
            with  t,nd,point({longitude:toFloat(nd.lon), latitude: toFloat(nd.lat)}) as point1, entity
                SET entity.p = point1
        with entity, t
        SET t.total = t.total + entity.lng
return t.total

1 Ответ

0 голосов
/ 02 июня 2019

Ваш запрос возвращает текущий t.total результат для узла вместо общего итогового значения.И, похоже, неправильно вычисляется расстояние для первого узла в сегменте (первый узел должен иметь расстояние 0).Это также очень неэффективно.Например, он не беспокоится об использовании отношения defines.В запросе neo4j жизненно важно использовать силу взаимосвязей, чтобы избежать сканирования большого количества не относящихся к делу данных.

Кроме того, нет никакого упоминания о конкретном "городе".Ваш запрос для всех Entity узлов.Если ваша БД содержит только Entity узлов для одного города, то это нормально.В противном случае вам нужно будет изменить запрос так, чтобы он совпадал только с Entity узлами для определенного города.

Следующий запрос может сделать то, что вы хотите (исходя из того, что я почерпнул из вашего вопроса, и предполагая, что ваша БДтолько данные для одного города), используя отношение defines для эффективного сопоставления узла start для каждого сегмента Entity и использование этого узла start для эффективного поиска интересующих узлов connected:

MATCH (entity:Entity {type:'road'})-[:defines]->(start)
MATCH p=(start)-[:connected* {entity_id:entity.id}]->(end)
WHERE NOT EXISTS((end)-[:connected {entity_id:entity.id}]->())
SET entity.lng = 0
SET entity.p = point({longitude:toFloat(start.lon), latitude: toFloat(start.lat)})
WITH entity, p
UNWIND TAIL(NODES(p)) AS nd
WITH point({longitude:toFloat(nd.lon), latitude: toFloat(nd.lat)}) as pt, entity
SET entity.lng = entity.lng + distance(entity.p, pt)
SET entity.p = pt
RETURN SUM(entity.lng) AS total

Функция агрегирования SUM() используется для возврата суммы lng для всех сущностей.Узел t не нужен.Предложение WHERE соответствует только путям, которые содержат полные сегменты.Этот запрос также инициализирует entity.p для point узла start и UNWINDS узлов после узла start.

Если существует много узлов Entity с typeзначения, отличные от «road», вы также можете создать index для :Entity(type).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...