Neo4j ShortestPath重复属性

时间:2018-09-17 13:01:45

标签: neo4j cypher

我目前正在使用Neo4j内置的最短路径算法。

public final class NumberToWordConverter {

    private final Long AND = null;
    private final Map<Long, String> map = new HashMap<>();

    {
        map.put(AND, "and");
        map.put(0L, "zero");
        map.put(1L, "one");
        map.put(2L, "two");
        map.put(3L, "three");
        map.put(4L, "four");
        map.put(5L, "five");
        map.put(6L, "six");
        map.put(7L, "seven");
        map.put(8L, "eight");
        map.put(9L, "nine");
        map.put(10L, "ten");
        map.put(11L, "eleven");
        map.put(12L, "twelve");
        map.put(13L, "thirteen");
        map.put(14L, "fourteen");
        map.put(15L, "fifteen");
        map.put(16L, "sixteen");
        map.put(17L, "seventeen");
        map.put(18L, "eighteen");
        map.put(19L, "nineteen");
        map.put(20L, "twenty");
        map.put(30L, "thirty");
        map.put(40L, "forty");
        map.put(50L, "fifty");
        map.put(60L, "sixty");
        map.put(70L, "seventy");
        map.put(80L, "eighty");
        map.put(90L, "ninety");
        map.put(100L, "hundred");
        map.put(1000L, "thousand");
        map.put(1000000L, "million");
        map.put(1000000000L, "billion");
    }

    public String numberToWords(long val) {
        String str = parts(Math.abs(val), 1, new LinkedList<>()).stream()
                                                                .map(map::get)
                                                                .collect(Collectors.joining(" "));
        return val < 0 ? "minus " + str : str;
    }

    private Deque<Long> parts(long val, long mul, Deque<Long> queue) {
        if (val >= 1000) {
            parts(val / 1000, mul * 1000, queue);

            if (val % 1000 > 0)
                parts(val % 1000, mul, queue);
        } else if (val <= 20) {
            if (mul == 1)
                queue.add(AND);

            queue.add(val);

            if (mul > 1)
                queue.add(mul);
        } else if (val < 100) {
            if (mul == 1)
                queue.add(AND);

            queue.add(val / 10 * 10);

            if (val % 10 > 0) {
                queue.add(val % 10);

                if (mul > 1)
                    queue.add(mul);
            }
        } else {
            queue.add(val / 100);
            queue.add(100L);

            if (val % 100 > 0)
                parts(val % 100, 1, queue);

            if (mul > 1)
                queue.add(mul);
        }

        return queue;
    }
}

问题是,当我运行算法时,尽管传递了第一个“ B”(橙色线),它仍可以返回第二个“ B”。我如何使它只返回“ B”的第一个实例?

我知道我可以使用唯一的ID来解决问题,但是我需要使用名称。

enter image description here

MATCH p = shortestpath((s:Node {Name: "A"})-[Link*1..500]->(e:Node {Name: "B"})) 
WHERE ALL(x in relationships(p) WHERE x.Value = true)
RETURN p

预先感谢,随时提出问题。

1 个答案:

答案 0 :(得分:1)

使用查询,neo4j将查找每个A节点和每个B节点,然后查找从每个A到每个B的所有最短路径。控制台UI中呈现的是该查询产生的所有结点,并具有将它们连接起来的每种关系。如果单击查询窗口左侧的 _Text _ 按钮,它将更加清楚正在发生的事情。对于A dn B节点之间匹配的每个最短路径,您都会看到一个谨慎的行。

在阅读完您的问题后,我希望您所遇到的是与特定A节点匹配的查询,然后遍历直到遇到B节点。

apoc路径扩展过程调用可能更适合您的需求。如果可以在B节点上添加标签B,则可以使用apoc.path.expand查找要查找的路径。

您可以使用以下方法设置B标签。

MATCH (n:Node {Name: 'B'}
SET n:B

这是一个使用apoc.path.expand的示例查询,该查询应在遇到的第一个B节点处停止。

MATCH (a:Node {Name: 'A'})
WITH a
CALL apoc.path.expand(a, 'Link', '+Node|/B', 1, 500) YIELD path
RETURN path