我正在尝试建模树结构的版本控制系统。这是一个例子:
树的第1版:
(一)及LT - [:belongs_to的] - (b)中
(一)及LT - [:belongs_to的] - (c)中
(d)< - [:belongs_to的] - (E)
树的第2版:
(一)及LT - [:belongs_to的] - (c)中
(d)< - [:belongs_to的] - (b)中
(d)< - [:belongs_to的] - (E)
因此,在版本2中,我将B移动到D.实际上我现在可以通过创建版本节点并将其与所有包含的节点相关联来实现此目的,并在每个BELONGS_TO关系上给出时间属性。所以图表看起来像这样:
版本1
MERGE (a:COMPONENT {name:'a'})
MERGE (b:COMPONENT {name:'b'})
MERGE (c:COMPONENT {name:'c'})
MERGE (d:COMPONENT {name:'d'})
MERGE (e:COMPONENT {name:'e'})
MERGE (version:VERSION {createdOn:'16-4-2015 12:17:00'})
MERGE (version)-[:CONTAINS]->(a)
MERGE (version)-[:CONTAINS]->(b)
MERGE (version)-[:CONTAINS]->(c)
MERGE (version)-[:CONTAINS]->(d)
MERGE (version)-[:CONTAINS]->(e)
MERGE (a)<-[:BELONGS_TO {createdOn:'16-4-2015 12:17:00'}]-(b)
MERGE (a)<-[:BELONGS_TO {createdOn:'16-4-2015 12:17:00'}]-(c)
MERGE (d)<-[:BELONGS_TO {createdOn:'16-4-2015 12:17:00'}]-(e)
RETURN *
第2版
MERGE (a:COMPONENT {name:'a'})
MERGE (b:COMPONENT {name:'b'})
MERGE (c:COMPONENT {name:'c'})
MERGE (d:COMPONENT {name:'d'})
MERGE (e:COMPONENT {name:'e'})
MERGE (version:VERSION {createdOn:'28-5-2015 13:00:00'})
MERGE (version)-[:CONTAINS]->(a)
MERGE (version)-[:CONTAINS]->(b)
MERGE (version)-[:CONTAINS]->(c)
MERGE (version)-[:CONTAINS]->(d)
MERGE (version)-[:CONTAINS]->(e)
MERGE (a)<-[:BELONGS_TO {createdOn:'28-5-2015 13:00:00'}]-(c)
MERGE (d)<-[:BELONGS_TO {createdOn:'28-5-2015 13:00:00'}]-(b)
MERGE (d)<-[:BELONGS_TO {createdOn:'28-5-2015 13:00:00'}]-(e)
RETURN *
我使用MERGE子句导入我的树结构,因为如果这些节点与新版本引用的节点相同,我想重用以前版本的节点。原因是树形结构中的每个节点都有映射,我不想丢失。
我的查询是这样的:
MATCH (version:VERSION)-[:CONTAINS]->(component:COMPONENT)
WHERE version.createdOn = '28-5-2015 13:00:00'
OPTIONAL MATCH
(component)-[rels:BELONGS_TO*]->(componentParents)
WHERE ALL(rel IN rels WHERE rel.createdOn = '28-5-2015 13:00:00')
RETURN *
问题是,我的方法是有效的,但是一旦树的版本变得非常大,我就会对性能感到担忧(让我们说10,000个版本,尽管可能它并不是真正的现实生活场景)。根据我的理解,它需要将不同的关系与不同的“已创造的”进行比较。获取所选版本的正确路径的值。 我的问题是,我的担忧是否正确?像这样对树结构图进行建模是否可以?如果不是,您会如何建议更好的模型?
提前感谢您,任何想法都将不胜感激!
答案 0 :(得分:6)
版本控制是一门非精确的科学,特别是在图表和用例中。根据您的需要,有很多方法可以做到。
当图表的大小增长时,您的模型可能会对性能产生影响。过滤关系或节点属性(未为关系编制索引)是非常昂贵的操作。通常,关系会将您带到图表并为其添加语义。
有一种表示节点状态的通用模式,例如您将拥有一个代表组件的唯一节点和多个 ComponentState 节点,这些节点将代表组件随时间的状态。
在一些Ascii-Art中你会得到:
(Component)-[:LAST_STATE]->(ComponentState {version:2})
-[:PREVIOUS_STATE]->(ComponentState {version: 1})
在图片中:
然后,这些ComponentState节点将与belongs_to组件节点建立关系。
我用你的例子创建了一个小的Neo4j控制台:
http://console.neo4j.org/r/4trq7i
如果你需要知道Instant的图形是什么(见这里的版本)1,你只需要在这一瞬间匹配State组件并遍历BELONGS_TO关系:
MATCH (n:ComponentState {version: 1})
MATCH (n)-[:BELONGS_TO]->(parent)
RETURN n.name, parent.name
将返回以下内容:
n.name parent.name
b a
c a
e d
因此,对于您的用例,您可以在此处添加代替版本的时间或使用TimeTree
如果需要,您可能还想在组件状态之间创建组件状态之间的关系。
希望这会对你有所帮助。