Запрашивая путь в Neo4j, как показать информацию об узле / крае только один раз? - PullRequest
0 голосов
/ 27 февраля 2019

Если был сделан простой запрос для пути между двумя узлами, скажем,

MATCH (m{name:'m'}), (n{name:'n'}),
   path = (m)-[:SOME_EDGE*]->(n)
RETURN path

EDIT: 
(example result)
...
segments: [
{
   start: {
      id: 1
      labels: [lbl1, lbl2, ...],
      properties: [p1, p2, ...]
   }
   end: { ... }
   properties: { ... }

},
{
   start: {
     id: 1
     labels: [lbl1, lbl2, ...]          <--- duplicate
     properties: [p1, p2, ...]          <--- duplicate
   }   
},
...
]

, то сгенерированный результат снова и снова содержит множество дубликатов свойств / типов / идентификаторов одинаковых узлов / ребер, и этостановится хуже, когда в путях есть циклы.

Я гуглил и обнаружил, что могу использовать проекции типа

return [node in nodes(path) | id(node)] as pathNodes, 
   [r in relationships(path) | id: id(r), type: type(r)] as rels

(Example result)
   { 
      pathNodes: [1,2,3],
      rels: {id:101,type:'SOME_EDGE'},{id:102,type:'SOME_EDGE'}
   },
   {
      pathNodes: [1,2,1,3],
      rels: ...
   }, ...

Но как добавить информацию об узлах / отношениях (только один раз для одной сущности)к приведенному выше результату?

Есть ли способ сделать это в одном запросе?

Ответы [ 2 ]

0 голосов
/ 16 июля 2019

stdob-- был прав насчет UNWIND и COLLECT, и мне не нужно было использовать APOC.

Я сам придумал решение несколько месяцев назад и пришел сюда сегодня, поэтому я выбрал его / ее ответ итакже опубликуйте мое решение без APOC здесь.

UNWIND и повторно СОБИРАЙТЕ ключ

MATCH p=(m{name:'m'})-[:'SOME_EDGE'|:'SOME_OTHER_EDGE'*1..2]->(n{name:'n'})
WITH {
  pathNodes: [node IN nodes(p) | ID(node)], 
  rels: [r IN RELATIONSHIPS(p) | {id:ID(r),ty:TYPE(r)}] 
} AS path, p
UNWIND NODES(p) AS node
RETURN {paths:COLLECT(path), nodes: COLLECT(DISTINCT{id:ID(node),name:node.name})}
0 голосов
/ 03 марта 2019

Вам необходимо собрать пути, узлы и отношения в отдельные списки, а затем составить карты на их основе, используя функцию apoc.map.setKey:

MATCH path = (A)-[*]->(B)
UNWIND nodes(path) AS n
UNWIND relationships(path) AS r
WITH 
  collect(DISTINCT path) as paths,
  collect(DISTINCT n) AS nodes, 
  collect(DISTINCT r) AS rels
RETURN
  [p IN paths | {
    nodes: [n IN nodes(p) | id(n)],
    rels: [r IN relationships(p) | id(r)]
  }] as paths,
  reduce(acc={}, n IN nodes | apoc.map.setKey(acc, toString(id(n)), n)) as nodes,
  reduce(acc={}, r IN rels | apoc.map.setKey(acc, toString(id(r)), r)) as rels
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...