Получение количества уникальных путей, пройденных при обходе с использованием API обхода Neo4j

Я создал следующий основной график:

CREATE (:NodeType1 {prop1:'value1'})-[:RelType1 {prop2:'value2'}]->(:NodeType2 {prop3:'value3'})-[:RelType2 {prop4:'value4'}]->(:NodeType3 {prop5:'value5'})-[:RelType3 {prop6:'value6'}]->(:NodeType4 {prop7:'value7'})

CREATE (:NodeType1 {prop1:'value8'})-[:RelType1 {prop2:'value9'}]->(:NodeType2 {prop3:'value10'})-[:RelType2 {prop4:'value11'}]->(:NodeType3 {prop5:'value12'})-[:RelType3 {prop6:'value13'}]->(:NodeType4 {prop7:'value14'})

MATCH path=(n:NodeType1 {prop1:'value1'})-[*]->(m:NodeType4 {prop7:'value7'})
CREATE (n)-[:RelType1 {prop2:'value15'}]->(:NodeType2 {prop3:'value16'})-[:RelType2 {prop4:'value17'}]->(:NodeType3 {prop5:'value18'})-[:RelType3 {prop6:'value19'}]->(m)

График выглядит так:

Когда я запускаю следующий шифр:

MATCH path=(a:NodeType1 {prop1:"value1"})-[:RelType1]->(b)-[:RelType2]->(c)-[:RelType3]->(d)
RETURN count(nodes(path))

я получил 2 в качестве выхода. Кажется, что nodes() на самом деле не возвращает количество узлов в пути, а просто количество строк в возвращаемом результате, так как если я верну path:

MATCH path=(a:NodeType1 {prop1:"value1"})-[:RelType1]->(b)-[:RelType2]->(c)-[:RelType3]->(d)
RETURN path

Я получаю две строки в возвращенном результате:

Теперь я думаю, как я могу получить тот же вывод при выполнении обхода с использованием API обхода Neo4J. Я получаю количество уникальных узлов в шифре следующим образом:

MATCH path=(a:NodeType1 {prop1:"value1"})-[:RelType1]->(b)-[:RelType2]->(c)-[:RelType3]->(d)
RETURN size(collect(distinct a))+size(collect(distinct b))+size(collect(distinct c))+size(collect(distinct d))

Вышеуказанный запрос корректно возвращает 6,

То же самое можно сделать в API обхода, используя статический счетчик внутри расширителя пути, который увеличивается каждый раз expand() называется. (Есть ли лучший подход для этого?)

public class MyPathExpander implements PathExpander{
    static int nodeCount = 0;

    @Override
    public Iterable expand(Path path, BranchState state) {
        Node lastNode = path.endNode();

        nodeCount++;  //**increment the count of nodes visited

        if(lastNode.hasLabel(MyLabels.NodeType1))
            return lastNode.getRelationships(MyRelations.RelType1, Direction.OUTGOING);
        else if (lastNode.hasRelationship(MyRelations.RelType1, Direction.INCOMING))
            return lastNode.getRelationships(MyRelations.RelType2, Direction.OUTGOING);
        else if (lastNode.hasRelationship(MyRelations.RelType2, Direction.INCOMING))
            return lastNode.getRelationships(MyRelations.RelType3, Direction.OUTGOING);
        else if (lastNode.hasRelationship(MyRelations.RelType3, Direction.INCOMING))
            return null;
        return null;
    }
}

Однако я не могу придумать, как подсказать количество уникальных путей, пройденных во время обхода при использовании API обхода (эквивалент выше RETURN count(nodes(path))). Как я могу это сделать? Разве это невозможно с API обхода?

PS: Под уникальным путем я подразумеваю уникальные перестановки порядка узлов, посещенных при обходе. Например, все a-b-c, a-c-b а также a-b-c-d уникальны

1 ответ

Этот запрос не возвращает количество уникальных путей, но количество всех путей, возвращаемых по запросу:

MATCH path=(a:NodeType1 {prop1:"value1"})-[:RelType1]->(b)
           -[:RelType2]->(c)-[:RelType3]->(d)
RETURN count(nodes(path))

Если вы хотите подсчитать количество уникальных узлов в запросе, вы можете сделать это:

MATCH path=(a:NodeType1 {prop1:"value1"})-[:RelType1]->(b)
           -[:RelType2]->(c)-[:RelType3]->(d)
UNWIND nodes(path) AS N
RETURN count(distinct N)

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

MATCH path=(a:NodeType1 {prop1:"value1"})-[:RelType1]->(b)
           -[:RelType2]->(c)-[:RelType3]->(d)
WITH path, 
     REDUCE(acc="", x in nodes(path) | acc + id(x)) +
     REDUCE(acc="", x in rels(path) | acc + id(x)) as uniID    
RETURN count(distinct uniID)
Другие вопросы по тегам