【问题标题】:Neo4J Cypher: filter out variable length paths by criteriaNeo4J Cypher:按标准过滤可变长度路径
【发布时间】:2017-06-14 23:27:42
【问题描述】:

我如何暗示对可变长度路径的限制?

我有来自一些start 节点查询的所有可能路径:

CREATE INDEX ON :NODE(id)
MATCH all_paths_from_Start = (start:Person)-[:FRIENDSHIP*1..20]->(person:Person)
WHERE start.id = 128 AND start.country <> "Uganda"
RETURN paths;

不,我想过滤掉至少有两个具有相同country 的人的所有路径。 我该怎么做?

【问题讨论】:

    标签: neo4j cypher variable-length


    【解决方案1】:

    1) 获取路径可能重复的国家/地区数组:REDUCE

    2) 去除重复并比较数组大小:UNWIND + COLLECT(DISTINCT...)

    MATCH path = (start:Person)-[:FRIENDSHIP*1..20]->(person:Person)
          WHERE start.id = 128 AND start.country <> "Uganda"
    WITH path, 
         REDUCE(acc=[], n IN NODES(path) | acc + n.country) AS countries
         UNWIND countries AS country
    WITH path, 
         countries, COLLECT(DISTINCT country) AS distinctCountries
         WHERE SIZE(countries) = SIZE(distinctCountries)
    RETURN path
    

    附: REDUCE 可以替换为 EXTRACT(感谢 Gabor Szarnyas):

    MATCH path = (start:Person)-[:FRIENDSHIP*1..20]->(person:Person)
          WHERE start.id = 128 AND start.country <> "Uganda"
    WITH path, 
         EXTRACT(n IN NODES(path) | n.country) AS countries
         UNWIND countries AS country
    WITH path, 
         countries, COLLECT(DISTINCT country) AS distinctCountries
         WHERE SIZE(countries) = SIZE(distinctCountries)
    RETURN path
    

    附言再次感谢 Gabor Szarnyas 提出的简化查询的另一个想法:

    MATCH path = (start:Person)-[:FRIENDSHIP*1..20]->(person:Person)
          WHERE start.id = 128 AND start.country <> "Uganda"
    WITH path
         UNWIND NODES(path) AS person
    WITH path, 
         COLLECT(DISTINCT person.country) as distinctCountries
         WHERE LENGTH(path) + 1 = SIZE(distinctCountries)
    RETURN path
    

    【讨论】:

    • 感谢您的回答!从性能的角度来看,它会是最佳选择吗?我将拥有一个非常大的数据集,最多有数百万个节点。有什么方法可以让查询更快?
    • @VolodymyrBakhmatiuk 查询中最重的部分是第一个MATCHMATCH path = (start:Person)-[:FRIENDSHIP*1..20]-&gt;(person:Person) WHERE start.id = 128 AND start.country &lt;&gt; "Uganda"。目前还不太明白如何改进它...
    • 至少我可以索引idcoutnry。如果您有任何想法,请告诉我
    • @stdob-- 我认为如果没有extract,我们可能会相处得很好:UNWIND NODES(path) AS node WITH path, COLLECT(node.country) AS countries, COLLECT(DISTINCT node.country) AS distinctCountries 我不确定它是否会对性能产生可衡量的影响,但它可能更容易阅读。
    • @GaborSzarnyas 是的,你是对的。根据您的想法添加了一个选项。
    【解决方案2】:

    我能想到的一个解决方案是获取路径的nodes,对于路径上的每个人,extract 来自同一国家的人数的值(我们通过@987654323 确定) @ing 为同一个国家/地区。如果一条路径有来自同一国家/地区的零个人,则该路径具有来自不同国家/地区的人员,即对于所有人,只有一个人(他/她本人)来自该国家/地区。

    MATCH p = (start:Person {id: 128})-[:FRIENDSHIP*1..20]->(person:Person)
    WHERE start.country <> "Uganda"
    WITH p, nodes(p) AS persons
    WITH p, extract(p1 IN persons | size(filter(p2 IN persons WHERE p1.country = p2.country))) AS personsFromSameCountry
    WHERE length(filter(p3 IN personsFromSameCountry WHERE p3 > 1)) = 0
    RETURN p
    

    查询在语法上是正确的,但我没有对任何数据进行测试。

    请注意,我将id = 128 条件移动到模式中并将all_paths_from_Start 变量缩短为p

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-26
      • 2015-04-06
      • 1970-01-01
      相关资源
      最近更新 更多