Neo4J孙子关系与节点相关联

时间:2014-08-03 17:50:22

标签: neo4j cypher

我正在尝试模拟Neo4J中的承包商关系,我正在努力解决如何概念化分包合同。我有政府机构(标签:代理商)和承包商(标签:公司)的节点。其中每个都具有HAS_OFFICE关系的地理空间Office节点。我正在考虑创建一个代表政府合同的节点(标签:合同)。

以下是我正在努力解决的问题:合同有一个政府机构(我认为这是一个“合同”关系)和一个或多个主要承包商(我认为这是一个“PRIME”) “关系)。这是复杂的地方。这些主要承包商中的每一个都只能在主合同下的分包商。从图形上看,这是:

(Agency) -[HAS_CONTRACT]-> (Contract) -[PRIME]-> (Company 1) -[SUB]-> (Company 2)

我正在努力解决的问题是[SUB]关系仅适用于某些合同 - 并非全部。例如:

Agency 1 -HAS-> Contract ABC -P-> Company 1 -S-> Company 2
Agency 1 -HAS-> Contract ABC -P-> Company 3 -S-> Company 4

Agency 2 -HAS-> Contract XYZ -P-> Company 1
Agency 2 -HAS-> Contract XYZ -P-> Company 4 -S-> Company 2

我想要一些方法来搜索,所以我可以问一些密码问题,例如“寻找代理商2可以将钱与公司2签订合同的方式”。它应该通过公司4与XYZ合同一起返回,而不是通过公司1的XYZ合同。

似乎可能存储和过滤关系中的数据会起作用,但我正在努力解决这个问题。我可以说Prima和Sub关系有一个属性,“contract_id”必须与Contract ['id']匹配吗?如果是这样,怎么样?

编辑:我不想指定查询的合同名称。根据@MarkM的回复,我想的是:

MATCH (a:Agency)-[:HAS]-(c:Contract)-[:PRIME {contract_id:c.id}]
                -(p:Company)-[:SUB {contract_id:c.id}]-(s:Company) 
RETURN s

我还希望能够使用shortestPath之类的东西来找到代理商和承包商之间的最短路径,该路径遵循单一合同ID。

3 个答案:

答案 0 :(得分:2)

我通过两个关系来创建分包商,一个是承包商,另一个是合同。

(:Agency)-[:ISSUES]->(con:Contract)-[:PRIMARY]->(contractor:Company)
(con:Contract)-[:SECONDARY]->(subContractor:Company)<-[:SUBCONTRACTS]-(contractor:Company)

也许您可以将用例模式化为graph-gist,这是记录和讨论建模问题的好方法。

答案 1 :(得分:1)

这看起来很简单;如果我误解了这个问题,我会道歉。

如果您想要分包商,您只需查询:

MATCH (a:Agency)-[:HAS]-(:Contract)-[:PRIME]-(p:Company)-[:SUB]-(s:Company) RETURN s

这将归还所有分包商公司。查询匹配整个模式。因此,如果您想要XYZ合约分包商,您只需给它参数:

MATCH (a:Agency)-[:HAS]-(:Contract {contractID: XYZ})-[:PRIME]-(p:Company)-[:SUB]-(s:Company) RETURN s

你只会得到公司2。

编辑:根据您的修改:

&#34;寻找代理商2可以将资金投入与公司2&#34; 的合同的方式 这似乎需要一些我不具备的特定领域知识。我假设代理商2只能把钱投入分包商而不是素数?如果你改写,我可能会帮忙,所以我们确切地知道你想从图中得到什么。根据我的阅读,您似乎希望所有公司都是公司2合同下的分包商。是吗?

如果这就是你想要的,那么你只需要给Neo道路:

MATCH (a:Agency: {AgencyID: 2)-[:HAS]
-(c:Contract)-[:PRIME]-(:Company)-[:SUB]-(s:Company: {companyID: 2)
RETURN c, s

这将为您提供XYZ下所有合同的清单,其中公司2是分包商。在当前示例中,它将是一行:[c:Contract XYZ,s:Company 2]。如果代理商2有更多合同,根据该合同,公司2分包,您将获得更多行。

您无法执行此操作:[:PRIME {contract_id:c.id}] [:SUB {contract_id:c.id}]因为Prime和Sub关系不应具有contract_id属性。他们不需要他们 - 他们与合同相关的事实就足够了。

如果分包商也有分包商,那么可能会使这一点变得更复杂的一件事情,但这并不明显。

答案 2 :(得分:1)

好的,2:

因此,原始示例数据中没有很好地捕获问题 - 抱歉错过了它。一个更好的例子是:

Agency 1 -HAS-> Contract ABC -P-> Company 1 -S-> Company 2
Agency 1 -HAS-> Contract XYZ -P-> Company 1 -S-> Company 3

现在,如果我问

MATCH (a:Agency)-[:HAS_CONTRACT]-(ABC:Contract {id:ABC})-[:PRIME]
-(c:Company)-[:SUBS]-(c2) RETURN c2

即使只有2个在ABC上,我也会得到公司2和公司3,对吗?

这里的问题是数据模型而不是查询。由于它们都直接连接到公司节点,因此无法区分公司的潜艇。您可以将子属关系中的属性与主要ID放在一起,但真正捕获信息的更好方法是在公司下添加另一个合同节点。是否将其标记为其他类型取决于您的具体情况。

公司1然后[:HAS]子公司所连接的合同。然后,合约可以指回主合同,其关系类似于[:PARENT][:PRIME],或者可能是从素数到子关系[:SUBCONTRACT]关系

现在一切都变得容易了。您可以找到特定合同下的所有分包合同,所有分包合同都包含特定公司[:HAS]等。要查找特定合同下的所有分包商,您可以查询以下内容:

MATCH (contract:Contract { id:"ContractABC" })-[:PRIME]-(c:Company)
-[:HAS]->(subcontract:Contract)-[:PARENT]-(contract)
WITH c, subcontract
MATCH (subcontract)-[:SUBS]-(subcontractor:Company)
RETURN c, subcontractor

这应该为您提供合同ABC下所有公司及其分包商的清单。在这种情况下,公司1,公司2(但不是公司3)。

这是一个控制台示例:http://console.neo4j.org/?id=flhv8e 我已离开原来的[:SUB]关系,但您可能不需要它们。