首页 文章

Neo4j:从叶子到父母的迭代,找到了普通的孩子

提问于
浏览
1

我已经将我的关系数据库迁移到neo4j,并且正在研究在我提交新系统之前是否可以实现某些功能 . 我刚读了两本neo4j书,但不幸的是它们没有涵盖我希望更加不言而喻的两个关键特征 . 我非常感谢有关这些事情是否易于实施或是否应该坚持使用sql的快速建议!谢谢!

我需要的功能是:1)我已经运行了一个脚本来分配:叶子标签到我树中叶子的所有节点 . 在已知节点与其相关叶节点之间的路径中,我的目标是为每个节点分配一个级别属性,该级别属性反映该节点来自已知节点(或叶节点 - 无论我能够最轻松地工作)的跳数 .

我试过了: match path=(n:Leaf)-[:R*]->(:Parent {Parent_ID: $known_value}) with n, length(nodes(path)) as hops set n.Level2=hops;

path=(n:Leaf)-[:R*]->(:Parent {Parent_ID: $known_value}) with n, path, length(nodes(path)) as hops foreach (n IN relationships (path) | set n.Level=hops);

第一个赋予属性,其值为仅包含叶节点的路径的全长 . 第二个为属性分配路径中所有关系的路径全长值 .

我应该使用shortestpath,为所有节点创建一个值为1的虚假属性,并迭代地添加该属性的权重?

2)我需要找到给定父节点的公共子节点 . 例如,我的孩子们各自[喜欢]很多电影,而且我想创建[:like]关系,从我自己到我孩子们都喜欢的电影(所以如果1个人喜欢看电影,那么我喜欢它,但如果只有3个像电影一样,没有任何事情发生) .

我找到了一个有三条路径的解决方案:Need only common nodes across multiple paths - Neo4j Cypher但我需要一个适用于任意数量路径的解决方案(从1开始) .

3)然后我计划从我最远的叶节点开始,创建与儿童电影的关系,并逐级向我的已知节点移动并重复创建关系,以便最顶级的祖父母只喜欢所有孩子的电影 . 所有孩子的孩子......]就像共同点一样,如果每个人都同意,那就是整个大家庭将在周六晚上观看的电影 .

这可以用neo4j完成吗?对于有基本Cypher的人来说,这项任务有多难?这主要是我在关系数据库中的表现/我是否应该在图数据库中完全不同地实现这一点?

非常感谢任何建议 . 谢谢!

1 回答

  • 0

    1.

    当已经匹配的起始节点和结束节点不是根和叶子时,shortestPath()可能会有所帮助,因为一旦找到第一个节点,它就不会继续查找其他路径 . 如果已经匹配的开始和结束节点是根和叶子,当图形是树结构(非循环)时,没有真正的理由使用shortestPath() .

    通常,当设置类似树中节点深度的东西时,您将使用 length(path) ,因此根将位于深度0,其子节点位于深度1处 .

    通常相对于根节点而不是叶节点计算深度(因为中间节点可以是在不同距离处的多个叶节点的祖先) . 将深度作为距离根部的距离使深度保持一致 .

    在关系上设置属性的方法将是一个问题,因为在不同深度的多个叶节点的多个路径中可以存在相同的关系 . 您的查询可能反复覆盖相同关系的属性,直到最后一次写入获胜 . 最好匹配所有节点(在查询中省略 :Leaf ),获取路径中的最后一个关系,并设置其深度:

    MATCH path=(:Parent {Parent_ID: $known_value})<-[:R*]-()
    WITH length(path) as length, last(relationships(path)) as rel
    SET rel.Level = length
    

    2.

    因此,如果树中父节点的所有子节点:像电影一样,则父节点应该:像电影一样 . 像这样的东西应该工作:

    MATCH path=(:Parent {Parent_ID: $known_value})<-[:R*0..]-(n)
    WITH n, size((n)<-[:R]-()) as childCount
    MATCH (n)<-[:R]-()-[:like]->(m:Movie)
    WITH n, childCount, m, count(m) as movieLikes
    WHERE childCount = movieLikes
    MERGE (n)-[:like]->(m)
    

    这里的想法是,对于电影,如果该电影节点的计数等于子节点的计数,则所有孩子都喜欢电影(假设节点只能:像同一电影一样) .

    这个查询不能用于从下到上构建喜欢,但是,喜欢这样的关系(喜欢个人喜欢而不喜欢因为所有孩子都喜欢它)必须首先出现在所有节点上才能使这个查询起作用 .

    3.

    为了实现自下而上的方法,您需要强制查询以特定顺序执行,我相信最好的方法是首先命令节点按深度顺序处理,然后使用apoc.cypher.doIt(),a在APOC Procedures中的proc,它允许您每行执行一次完整的Cypher查询,以进行计算 .

    这种方法应该有效:

    MATCH path=(:Parent {Parent_ID: $known_value})<-[:R*0..]-(n)
    WHERE NOT n:Leaf // leaves should have :like relationships already created
    WITH n, length(path) as depth, size((n)<-[:R]-()) as childCount
    ORDER BY depth DESC
    CALL apoc.cypher.doIt("
     MATCH (n)<-[:R]-()-[:like]->(m:Movie)
     WITH n, childCount, m, count(m) as movieLikes
     WHERE childCount = movieLikes
     MERGE (n)-[:like]->(m)
     RETURN count(m) as relsCreated",
     {n:n, childCount:childCount}) YIELD value
    RETURN sum(value.relsCreated) as relsCreated
    

    也就是说,我不确定这会做你认为会做的事情 . 或者更确切地说,它只会按照您认为的方式工作,如果唯一的:像电影的关系最初只设置在叶节点上,并且(在运行此传播查询之前)树中没有其他中间节点具有:与电影的关系 .

相关问题