在Neo4j中将星型拓扑转换为链接列表

时间:2014-01-28 02:52:37

标签: linked-list neo4j cypher

当我最初创建我的数据集时,我认为星形拓扑结构会很好,但是现在我已经获得了一些示例数据,我宁愿使用linked list拓扑。现在我想只使用Cypher进行就地转换,并在一次调用中进行。这可能吗?

使用简化示例:Blog节点可以有多个子节点Post,所以我直接将它们连接起来:

CREATE (a:Blog), (a)-[:HAS]->(b:Post), (a)-[:HAS]->(c:Post)
RETURN a,b,c

现在,随着我的设计的进展,我认为我宁愿把它作为一个链接列表,就像这样(假设已经创建了:FIRST帖子):

MATCH (a:Blog)-[r:FIRST]->(b:Post)
CREATE (a)-[:FIRST]->(c:Post)-[:PREV]->(b)
DELETE r
RETURN a,b,c

所以我可以很好地编码链表。我需要做的是将旧星形拓扑转换为新的链表格式。我尝试了很多东西,但没有任何效果,所以这是我最好的猜测,但是完全没有功能的代码:

MATCH (b:Blog)-[:HAS]-(p:Post)
WITH b, collect(p) as posts
CREATE b-[:FIRST]->posts[0]
FOREACH( i IN range(1,len(posts)-1) |
    CREATE posts[i]-[:PREV]->posts[i-1]
)
RETURN b,p

索引集合似乎不适用于CREATE语句(FOREACH内部或外部)。

有什么方法可以实现这种翻译吗?

修改 我认为另一种方法可能是使用序数值标记帖子并对顺序序数进行一些迭代,但是在尝试添加序数时出现语法错误:

MATCH (b:Blog)-[:HAS]-(p:Post)
WITH b, collect(p) as posts
FOREACH( i in range(0,length(posts)) |
    SET posts[i].ordinal = i
}

语法错误是:

Invalid input '[': expected an identifier character, node labels, a property map, a relationship pattern, '(', '.' or '=' (line 4, column 14)
"    SET posts[i].ordinal = i"
              ^

修改/ 2

我的另一个想法是将链接列表代码放在FOREACH中,但由于MATCH无法在FOREACH内使用,因此失败了。首先,我创建并附加了一个虚拟(b:Blog)-[:FIRST]->(p:Post)关系,然后编写了这个查询(这不起作用):

MATCH (f)<-[:FIRST]-(b:Blog)-[:HAS]->(p:Post)
WITH b, collect(p) as posts
FOREACH( x IN posts |
    MATCH (b)-[r:FIRST]->(f) 
    DELETE r
    CREATE (b)-[r2:FIRST]->(x), (x)-[:PREV]->(f)
)
RETURN b-[*0..1]-()

2 个答案:

答案 0 :(得分:3)

作为一个拐杖直到你找到一个更好的workarund,你可以尝试在原始的foreach循环中嵌套FOREACH (a IN [posts[i]] | FOREACH (b IN [posts[i-1]] | CREATE a-[:PREV]->b)),作为解压缩索引切片的方法。对于编辑1,请尝试SET (posts[i]).ordinal = i。我想我在某个地方有一个更好的解决方法,但现在不记得了,如果我发现它我就会把它搞定。

答案 1 :(得分:-1)

尝试此Cypher查询

编辑后

MATCH (a:Blog)-[r:HAS]->(p:Post)
WITH a,r,collect(p) as posts,range(1,length(posts)) as rel
MERGE(firstPost:Post {created: head(posts).created , otherprop: head(posts).otherprop})
CREATE a-[:FIRST]->(firstPost)
FOREACH(i IN rel | 
MERGE(thisPost:Post {created: (posts[i]).created , otherprop: (posts[i]).otherprop})
MERGE(prevPost:Post {created: (posts[i-1]).created , otherprop: (posts[i-1]).otherprop})
CREATE (prevPost)-[:NEXT]->(thisPost))
WITH a
MATCH a-[r:HAS]->() delete r

这将创建类似(博客) - [第一] - &gt;(发布) - [下一步] - &gt;(发布)...... 默认情况下,Cypher按自然升序对COLLECT(p)中的元素进行排序。因此,如果您只创建了属性,它将最后排序最近的属性,因此从BLOG开始的下一个链中的最后一个节点将是与POST关联的最新BLOG