Ограничить Neo4j apo c .path.expand значением свойства отношения - PullRequest
0 голосов
/ 11 июля 2020

Возможно ли на взвешенном графе Neo4j найти все пути в пределах n переходов данного узла с ограничениями, согласно которым возвращаются / расширяются только верхние m отношений (по весу) от каждого узла?

Например, учитывая следующий график:

введите описание изображения здесь

Этот запрос ...

MATCH (n0:Foo {n: "a"})
CALL apoc.path.expand(n0, "TO>", "", 1, 3)
YIELD path as p
WHERE ALL (x in relationships(p) where x.score > 0.02)  // Additional constraint not directly related to the question
RETURN p, length(p) AS hops
ORDER BY hops

... возвращает:

╒═══════════════════════════════════════════════════════════════════════╤══════╕
│"p"                                                                    │"hops"│
╞═══════════════════════════════════════════════════════════════════════╪══════╡
│[{"n":"a"},{"score":0.03},{"n":"d"}]                                   │1     │
├───────────────────────────────────────────────────────────────────────┼──────┤
│[{"n":"a"},{"score":0.03},{"n":"d"},{"n":"d"},{"score":0.11},{"n":"k"}]│2     │
├───────────────────────────────────────────────────────────────────────┼──────┤
│[{"n":"a"},{"score":0.03},{"n":"d"},{"n":"d"},{"score":0.1},{"n":"j"}] │2     │
├───────────────────────────────────────────────────────────────────────┼──────┤
│[{"n":"a"},{"score":0.03},{"n":"d"},{"n":"d"},{"score":0.12},{"n":"l"}]│2     │
└───────────────────────────────────────────────────────────────────────┴──────┘

Возможно ли также ограничить исходящие отношения из каждый узел, например, до 2 лучших по количеству очков .

Ожидаемый результат:

╒═══════════════════════════════════════════════════════════════════════╤══════╕
│"p"                                                                    │"hops"│
╞═══════════════════════════════════════════════════════════════════════╪══════╡
│[{"n":"a"},{"score":0.03},{"n":"d"}]                                   │1     │
├───────────────────────────────────────────────────────────────────────┼──────┤
│[{"n":"a"},{"score":0.03},{"n":"d"},{"n":"d"},{"score":0.11},{"n":"k"}]│2     │
├───────────────────────────────────────────────────────────────────────┼──────┤
│[{"n":"a"},{"score":0.03},{"n":"d"},{"n":"d"},{"score":0.12},{"n":"l"}]│2     │
└───────────────────────────────────────────────────────────────────────┴──────┘

1 Ответ

1 голос
/ 11 июля 2020

Я не думаю, что вы можете сделать это за один go, потому что вам нужно сравнивать каждый шаг на каждом пути.

Также вы должны подумать о случае, когда у вас есть оценки вроде 0,09,0,11,0,11,0,12, в котором выбор 2-х лучших может вернуть произвольные результаты.


MATCH p=(n0)-[:TO*1..3]->()
// From starting node
WHERE n0.n='a'
// get for each node the scores of the outgoing reps, sort them and get the second one
// and put them in an array
WITH p,
     REDUCE (array=[], n IN [x in nodes(p) WHERE (x)-[:TO]->()] |
             (array
             + apoc.coll.sort([(n)-[r:TO]->() | r.score])[1])
            ) AS cutOffScoresByStep
WITH p,cutOffScoresByStep

// only get the paths where the score on each rel is higher than the corresponding cutOffScore
WHERE ALL (rel IN relationships(p) 
           WHERE rel.score >= cutOffScoresByStep[apoc.coll.indexOf(relationships(p),rel)]
          )
             
RETURN p
...