How to represent non unique parent-child relationship as graph?

六月ゝ 毕业季﹏ 提交于 2021-01-29 11:36:47

问题


I want to see if there is a way to represent/model a nested parent-child relationship in a graph db platform like neo4j or arangodb.

In particular, I am trying to model the contractor/subcontractor relations over multiple contracts:

example contract relations image link

I can see how this can be done using a table where both the parent and the contract are represented. I can't see how to do this in a graph since there can be multiple A-B relations but for different contracts.


回答1:


Using ArangoDB

The best thing to do here is create three collections, and I've created some sample data and sample queries to show you how it can work.

  • contracts: A document collection that contains contracts
  • companies: A document collection that contains companies
  • company_contracts: An edge collection that contains connections between contracts and companies

The goal is to store your contracts and companies in their respective collections and then store the relationshps in the company_contracts edge collection.

Because the companies are reused across multiple contracts, it will therefore be necessary to be able to filter on the relationships, based on the contract code.

Each contract has a key called code which contains an identifier for that contract (e.g. 'Contract 1' has a code of 1). Note: I've also added a code field to each company, but that's not necessarily required for this example.

Each relationship that is added to the company_contracts edge collection will have a key added to it to identify what contract that edge is for, and this key is called contract_code.

This will be used in your AQL query to ensure you only select edges related to your contract in question.

To create the base data, you run this script in the arangodsh tool, just start it and then once you've provided your password and are connected, just paste this block of text in to create the sample collections and load some base data.

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});

Once you've done that, this is an example AQL query you could use to find all relationships for a given contract code:

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

If you pass a value of 1 as the value for the contract_code parameter, you'll get the result as shown by your sample document, and if you provide the values 2 or 3 it will show those results.

The query works by doing two things:

  • The LET query finds the _id of the contract you're interested in
  • The GRAPH query then finds all outbound connections from that contract, and it applies a filter to ALL edges in each path coming out of that contract, ensuring every single edge has a company_code key that matches the contract code you're working with

This FILTER ... ALL condition ensures you only get edges related to your contract.

The view of the results looks like this in the ArangoDB graph viewer for the results for Contract 1:



来源:https://stackoverflow.com/questions/56034784/how-to-represent-non-unique-parent-child-relationship-as-graph

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!