Как получить список уникальных путей между двумя узлами в моем графике neo4j, используя шифр?

1

Таким образом, у меня есть ориентированный граф в neo4j, который имеет два типа узлов, например A и B. В основном в верхней точке A указывает на множество B, каждая из которых указывает на многие A, рекурсивно вниз. Что-то вроде этого:

A1 → B1, B2, B3

B1 → A3, A4, A7

B2 → A5, A6, A8

A3 → B3

A4 → B3

A5 → B3

B3 → A9

В любом случае, взяв два разных A, я хочу запустить запрос, чтобы получить все уникальные пути между этими двумя A. Поэтому, учитывая A1 и A9 выше, я хотел бы получить следующее:

A1 → B1 → A3 → B3 → A9,

A1 → B1 → A4 → B3 → A9,

A1 → B2 → A5 → B3 → A9,

A1 → B3 → A9

Если возможно, я хотел бы удалить B из одного и того же запроса (так как они не нужны для этого конкретного случая), поэтому конечный результат будет следующим:

A1 → A3 → A9,

A1 → A4 → A9,

A1 → A5 → A9,

A1 → A9

Если нет, я могу сделать это вручную, хотя в запросе будет лучше. Как именно я должен сформировать этот запрос?

До сих пор у меня есть что-то вроде этого:

var dic = new Dictionary<string, object> {{a1.toString(), a1}, {a2.toString(), a2}};

var query = _graphClient.Cypher
    .Start(dic)
    .Match(String.Format("p={0}-[*]->{1}", a1.toString(), a2.toString()))
    //I don't know what goes here exactly... .Return(something)
    .Results;

return query.Single();

Я думаю, что мне нужно сделать что-то с несколькими запросами на шифрование, чтобы лишить B. Возможно, что-то вроде использования этого в качестве посредника и применения его к любой глубине:

a1-[]->b-[]->a2
return a1, a2;

Любая помощь будет потрясающей! Спасибо вам раньше времени !!!

Обновить

С комментарием Christophe Willemsen и этим сообщением (Neo4j.NET Client - получение пути от узла к его корню) я смог получить следующий код С#, который делает все, кроме удаления B с пути:

var query = _graphClient.Cypher
    .Match("p = (a2:A)-[*]->(a1:A)")
    //Where and AndWhere for matching a1 and a2 as necessary
    .Return<IEnumerable<A>>("nodes(p)")
    .OrderByDescending("length(p)")
    .Results
    .SelectMany(result => new List<List<A>> {result.ToList()});

return query.ToList();

Если кто-то знает, как указать узлам (p) только возвращать A, это должно сделать это. Я могу просто перебирать каждый путь, удаляя B, но это не очень эффективно, если их много, особенно если есть какой-то отличный способ шифрования. Спасибо за помощь до сих пор!

  • 0
    Шифр для фильтрации nodes (p) с меткой будет FILTER (n IN NODES (p) WHERE n:A) . Не уверен, как вы это сделаете в свободном клиенте шифра, если вам нужно использовать метод .Filter или вы можете просто добавить функцию фильтра шифра в строку, передаваемую в качестве аргумента .Return .
Теги:
neo4j
neo4jclient

2 ответа

1

Вы можете, возможно, использовать алгоритм allShortestPaths вместе с такими как:

MATCH (a:A { name:'A1' }),(aa:A { name:'A8' }), p = allShortestPaths((a)-[*]-(aa))

RETURN DISTINCT (p), collect(nodes(p)) AS x

ORDER BY length(p) DESC 

LIMIT 5

Я установил консоль neo4j в виде песочницы, доступной здесь: http://console.neo4j.org/?id=pjf2qg

Я борюсь за то, как удалять узлы B из результатов btw

Обновить

Я закончил, чтобы извлечь только узлы с метками A из путей:

MATCH (a:A {name:'A1'}),(aa:A {name:'A8'}),
p = allShortestPaths((a)-[*]-(aa))
WITH DISTINCT(p) as pths, COLLECT(nodes(p)) as x
UNWIND(x) as u
WITH FILTER(s IN u WHERE 'A' IN labels(s)) AS zz, pths as paths
RETURN paths, zz

Крис

  • 0
    Ответ изменен
  • 0
    nodes (p) уже возвращает коллекцию, если вы collect ее снова, у вас есть (один элемент) коллекция коллекции всех узлов в p . Если вы не соберете его, вам также не придется раскручиваться перед фильтрацией, но вы можете отфильтровать сразу. a:A также является допустимым предикатом, поэтому вы можете проверить этот способ вместо строкового представления метки в labels . Вот как это может выглядеть: console.neo4j.org/?id=z6lqc3
0

Мой первый ответ был отредактирован с помощью рабочего запроса.

Кстати, пытаясь найти этот запрос, я нашел следующее:

При попытке фильтровать коллекцию узлов (p) без размотки идентификатор не рассматривается как узел, а как сборник, я не знаю, является ли это ожидаемым поведением:

Следующий запрос не будет подтверждать, что идентификатор s представляет собой коллекцию, и ожидается, что узел

MATCH (a:A {name:'A1'}),(aa:A {name:'A8'}),
p = allShortestPaths((a)-[*]-(aa))
WITH p as paths, COLLECT(nodes(p)) as x
WITH filter(s IN x WHERE 'A' IN labels(s)) AS zz
RETURN zz

Ещё вопросы

Сообщество Overcoder
Наверх
Меню