2016-12-25 2 views
0

Я пытаюсь получить шифр, который может дать мне маршруты и доступные места для источника до места назначения. Ниже приведена моя установка графикаПути Neo4j с фильтрами

create (t1:Trip{id:"red"}), (t2:Trip{id:"blue"}), (a:City{id:"A"}), (b:City{id:"B"}), (c:City{id:"C"}), (d:City{id:"D"}) 
create (t1)-[:stop_at]->(a),(t1)-[:stop_at]->(b),(t1)-[:stop_at]->(c),(t1)-[:stop_at]->(d),(t2)-[:stop_at]->(a),(t2)-[:stop_at]->(b),(t2)-[:stop_at]->(c),(t2)-[:stop_at]->(d) 
create (a)-[:red]->(b),(b)-[:red]->(c),(c)-[:red]->(d) create (a)-[:blue]->(b),(b)-[:blue]->(c),(c)-[:blue]->(d) 
create (b)-[:red_01{seat:40}]->(c),(c)-[:red_01{seat:40}]->(d) 

У меня есть две «поездки», «красный» и «синий». Связи, созданные между узлами (стопами) с использованием идентификатора «Trip», являются только абстрактными ссылками. Я хотел бы искать поездки, которые останавливаются на «A» и «D», и я использовал следующий запрос, который возвращает поездки «красный» и «синий».

match (t:Trip)-[:stop_at]->(c:City) where c.id = "A" or c.id = "D" return distinct t.id 

Тогда я хотел бы получить пути, и я использую следующий запрос.

match (t:Trip)-[:stop_at]->(c:City) where c.id = "A" or c.id = "D" with distinct t.id as id 
match (source:City{id:"A"})-[rel*]->(dest:City{id:"D"}) where all(item in rel where starts with id) return rel 

Он возвращает 36 рядов, которые объединяют все возможные пути. Например:

[(A)-[:blue]->(B), (B)-[:blue]->(C), (C)-[:blue]->(D)] 
[(A)-[:red]->(B), (B)-[:red]->(C), (C)-[:red]->(D)] 
[(A)-[:red]->(B), (B)-[:red]->(C), (C)-[:red_01 {seat:40}]->(D)] 
[(A)-[:red]->(B), (B)-[:red_01 {seat:40}]->(C), (C)-[:red]->(D)] 
[(A)-[:red]->(B), (B)-[:red_01 {seat:40}]->(C), (C)-[:red_01 {seat:40}]->(D)] 

То, что я хотел бы получить это следующим образом:

[(A)-[:blue]->(B), (B)-[:blue]->(C), (C)-[:blue]->(D)] 
[(A)-[:red]->(B), (B)-[:red_01 {seat:40}]->(C), (C)-[:red_01 {seat:40}]->(D)] 

суффикс «_01» означает, что есть продажи для этой даты/времени поездки между двумя остановками. Для всех «красных» поездок мне хотелось бы получить только путь, в который включено максимальное количество продаж. Если мы посмотрим на результат выше, это будет строка № 5. «Синяя» поездка не имеет продаж в этот день, и поэтому мы сохраним ее в результате.

Это консоль neo4j для справки. Большое спасибо за Вашу помощь.

http://console.neo4j.org/?id=2sho3j

Райан

+0

Хороший вопрос - спасибо за предоставление образцов наборов данных и описывающих вашу проблему в деталях. Тем не менее, ваш третий фрагмент запроса не компилируется: 'где все (элемент в rel, где начинается с id)' что-то отсутствует. Правильное выражение должно выглядеть как 'WHERE ... STARTS WITH ...' –

ответ

0

Этот запрос является шагом к ответу на ваше решение:

match (t:Trip)-[:stop_at]->(c:City) 
where c.id = "A" or c.id = "D" 
with distinct t.id as id 
match (source:City{id:"A"})-[rel*]->(dest:City{id:"D"}) 
where all(item in rel where type(item) starts with id) 
return rel, extract(r in rel | type(r)) as reltypes 

Она возвращает:

╒════════════════════════════╤═════════════════════╕ 
│rel       │reltypes    │ 
╞════════════════════════════╪═════════════════════╡ 
│[{}, {}, {}]    │[blue, blue, blue] │ 
├────────────────────────────┼─────────────────────┤ 
│[{}, {seat: 40}, {}]  │[red, red_01, red] │ 
├────────────────────────────┼─────────────────────┤ 
│[{}, {seat: 40}, {seat: 40}]│[red, red_01, red_01]│ 
├────────────────────────────┼─────────────────────┤ 
│[{}, {}, {}]    │[red, red, red]  │ 
├────────────────────────────┼─────────────────────┤ 
│[{}, {}, {seat: 40}]  │[red, red, red_01] │ 
└────────────────────────────┴─────────────────────┘ 

Однако, я думаю, что мы должны улучшить данные модель первая:

  • Использование суффикса в типе отношений для сигнализации того, что может часто меняться (здесь, чтобы сигнализировать о продаже) - плохая идея. Я рекомендую использовать свойства отношений, например. sale: true/false или добавление дней продажи в виде списка (даты хранения могут быть сложными: используйте временные метки, строку, APOC date/time support - все, что подходит для вашего варианта использования).
  • Вы также можете рассмотреть возможность сохранения цвета маршрута в качестве свойства, например. (a)-[:ROUTE {colour: 'red'}]->(b) (ROUTE должен быть как можно более наглядным, например TRAIN или, возможно, CONNECTED_BY_TRAIN).

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

reduce:

match (t:Trip)-[:stop_at]->(c:City) 
where c.id = "A" or c.id = "D" 
with distinct t.id as id 
match (source:City{id:"A"})-[rel*]->(dest:City{id:"D"}) 
where all(item in rel where type(item) starts with id) 
return rel, extract(r in rel | type(r)) AS reltypes, 
    reduce(
    noSales = 0, 
    item IN rel | noSales + 
     case type(item) ends with '_01' 
     when true then 1 
     else 0 
     end) AS noSales 

Или немного проще ширина filter и length:

match (t:Trip)-[:stop_at]->(c:City) 
where c.id = "A" or c.id = "D" 
with distinct t.id as id 
match (source:City{id:"A"})-[rel*]->(dest:City{id:"D"}) 
where all(item in rel where type(item) starts with id) 
return rel, extract(r in rel | type(r)) AS reltypes, 
    length(filter(item in rel where type(item) ends with '_01')) AS noSales 

Оба возвращают следующий RESU л:

╒════════════════════════════╤═════════════════════╤═══════╕ 
│rel       │reltypes    │noSales│ 
╞════════════════════════════╪═════════════════════╪═══════╡ 
│[{}, {}, {}]    │[blue, blue, blue] │0  │ 
├────────────────────────────┼─────────────────────┼───────┤ 
│[{}, {seat: 40}, {}]  │[red, red_01, red] │1  │ 
├────────────────────────────┼─────────────────────┼───────┤ 
│[{}, {seat: 40}, {seat: 40}]│[red, red_01, red_01]│2  │ 
├────────────────────────────┼─────────────────────┼───────┤ 
│[{}, {}, {}]    │[red, red, red]  │0  │ 
├────────────────────────────┼─────────────────────┼───────┤ 
│[{}, {}, {seat: 40}]  │[red, red, red_01] │1  │ 
└────────────────────────────┴─────────────────────┴───────┘ 

Чтобы получить больше продаж, у вас есть только для сортировки и получить главный результат:

order by noSales desc 
limit 1 
Смежные вопросы