Таким образом, у меня есть ориентированный граф в 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, но это не очень эффективно, если их много, особенно если есть какой-то отличный способ шифрования. Спасибо за помощь до сих пор!
Вы можете, возможно, использовать алгоритм 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
Крис
nodes (p)
уже возвращает коллекцию, если вы collect
ее снова, у вас есть (один элемент) коллекция коллекции всех узлов в p
. Если вы не соберете его, вам также не придется раскручиваться перед фильтрацией, но вы можете отфильтровать сразу. a:A
также является допустимым предикатом, поэтому вы можете проверить этот способ вместо строкового представления метки в labels
. Вот как это может выглядеть: console.neo4j.org/?id=z6lqc3
Мой первый ответ был отредактирован с помощью рабочего запроса.
Кстати, пытаясь найти этот запрос, я нашел следующее:
При попытке фильтровать коллекцию узлов (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
nodes (p)
с меткой будетFILTER (n IN NODES (p) WHERE n:A)
. Не уверен, как вы это сделаете в свободном клиенте шифра, если вам нужно использовать метод.Filter
или вы можете просто добавить функцию фильтра шифра в строку, передаваемую в качестве аргумента.Return
.