首页 > 解决方案 > 如何将非唯一的父子关系表示为图形?

问题描述

我想看看是否有一种方法可以在 neo4j 或 arangodb 等图形数据库平台中表示/建模嵌套的父子关系。

特别是,我正在尝试对多个合同的承包商/分包商关系进行建模:

示例合同关系图片链接

我可以看到如何使用代表父级和合同的表来完成此操作。我看不到如何在图表中执行此操作,因为可以有多个 AB 关系但针对不同的合同。

标签: neo4jarangodb

解决方案


使用 ArangoDB

这里最好的做法是创建三个集合,我创建了一些示例数据和示例查询来向您展示它是如何工作的。

  • 合同:包含合同的文档集合
  • 公司:包含公司的文档集合
  • company_contracts:包含合同和公司之间连接的边缘集合

目标是将您的合同和公司存储在它们各自的集合中,然后将关系存储在 company_contracts 边缘集合中。

由于公司在多个合同中重复使用,因此有必要能够根据合同代码过滤关系。

每个合同都有一个名为的密钥code,其中包含该合同的标识符(例如,“合同 1”有一个codeof 1)。注意:我还code为每家公司添加了一个字段,但本示例不一定需要这样做。

添加到company_contracts边缘集合的每个关系都将添加一个键,以标识该边缘用于什么合同,这个键称为contract_code

这将在您的 AQL 查询中使用,以确保您只选择与相关合同相关的边。

要创建基础数据,您在工具中运行此脚本arangodsh,只需启动它,然后在您提供密码并连接后,只需粘贴此文本块即可创建示例集合并加载一些基础数据。

var contracts = db._create("contracts");
var companies = db._create("companies");
var company_contracts = db._createEdgeCollection("company_contracts");

var contract_1 = contracts.save({_key: "1", title:"Contract 1", code: 1})._id;
var contract_2 = contracts.save({_key: "2", title:"Contract 2", code: 2})._id;
var contract_3 = contracts.save({_key: "3", title:"Contract 3", code: 3})._id;

var company_a = companies.save({_key: "a", title:"Company A", code: "A"})._id;
var company_b = companies.save({_key: "b", title:"Company B", code: "B"})._id;
var company_c = companies.save({_key: "c", title:"Company C", code: "C"})._id;
var company_d = companies.save({_key: "d", title:"Company D", code: "D"})._id;
var company_e = companies.save({_key: "e", title:"Company E", code: "E"})._id;

company_contracts.save(contract_1, company_a, { contract_code: 1});
company_contracts.save(company_a, company_c, { contract_code: 1});
company_contracts.save(company_a, company_b, { contract_code: 1});
company_contracts.save(company_c, company_d, { contract_code: 1});
company_contracts.save(company_c, company_e, { contract_code: 1});

company_contracts.save(contract_2, company_c, { contract_code: 2});
company_contracts.save(contract_2, company_a, { contract_code: 2});
company_contracts.save(company_a, company_b, { contract_code: 2});
company_contracts.save(company_c, company_d, { contract_code: 2});

company_contracts.save(contract_3, company_b, { contract_code: 3});
company_contracts.save(company_b, company_c, { contract_code: 3});
company_contracts.save(company_b, company_a, { contract_code: 3});

完成后,这是一个示例 AQL 查询,您可以使用它来查找给定合约代码的所有关系:

LET contract_id = FIRST(FOR d IN contracts FILTER d.code == @contract_code RETURN d._id)

FOR v, e, p IN 1..10 OUTBOUND contract_id company_contracts
FILTER p.edges[*].contract_code ALL == @contract_code
RETURN p

如果您将值1作为contract_code参数的值传递,您将获得示例文档所示的结果,并且如果您提供值23它将显示这些结果。

查询通过做两件事来工作:

  • LET查询找到_id您感兴趣的合同
  • 然后,GRAPH查询从该合约中找到所有出站连接,并将过滤器应用于从该合约ALL出来的每条路径中的边,确保每条边都有一个company_code与您正在使用的合约代码匹配的密钥

FILTER ... ALL条件可确保您仅获得与合同相关的优势。

在 ArangoDB 图形查看器中,合同 1 的结果视图如下所示:

合同 1 的样本结果


推荐阅读