关于多个TAG组合关联的schema设计问题

刚接触nebula graph不久,在实际业务场景建模时遇到如下问题,希望各位大佬不吝赐教,万分感谢!

【问题描述】:
当前正在使用图数据库对组内业务知识进行梳理,现把遇到的问题简单抽象一下,schema 包括三个Tag: 版本(name string)、组件(name string)、代码看护方式(name string)。
edge type: contains
关系:版本—contains–>组件, 组件------contains---->看护方式

用具体数据描述三者之间的对应关系:

版本 组件 看护方式
1.0 A IDE级
1.0 A 门禁级
1.0 B IDE级
1.0 B 门禁级
1.0 C 门禁级
2.0 A IDE级
2.0 B IDE级
2.0 B 门禁级

建好schema,插入csv格式的数据为:

版本.csv
v_00 1.0
v_01 2.0

组件.csv
c_00 A
c_01 B
c_02 C

看护方式.csv
n_00 IDE级
n_01 门禁级

版本_组件_contains.csv
v_00 c_00
v_00 c_01
v_00 c_02
v_01 c_00
v_01 c_01

组件_看护方式_contains.csv
c_00 n_00
c_00 n_01
c_01 n_00
c_01 n_01
c_02 n_01

这样插入数据后,我发现在查询时会有信息丢失,比如查询出来版本2.0的A组件包含两种看护方式(IDE级 门禁级),但实际上版本2.0的A组件只包含一种看护方式(IDE级)。

不知道是我的schema设计有问题,还是插入的数据有问题, 对于这种表达三个甚至多个的TAG组合关联的信息 应该如何处理?

schema 没有问题,而是你插入了两点之间的多边关系,这边都是值不一样的,你需要用到 rank,不然就是当你重复插入相同边,会进行覆盖写,最后只留下一条边。

参考:https://docs.nebula-graph.com.cn/3.6.0/3.ngql-guide/13.edge-statements/1.insert-edge/ ( 在这个页面 comman + f / ctrl+ f 搜 “rank” 看具体的说明)

非常感谢您的解答,我还有一个疑问,上面描述的是三个TAG之间的组合关联关系,使用rank来区分确实可行,rank可以表示版本信息,如下数据所示:
组件_看护方式_contains.csv
组件_vid 看护方式_vid rank(1 对应版本1.0,2对应版本2.0)
c_00 n_00 1
c_00 n_01 1
c_01 n_00 1
c_01 n_01 1
c_02 n_01 1
c_00 n_00 2
c_01 n_00 2
c_01 n_01 2
那如果是四个Tag或者5个Tag呢? 比如新增一个Tag:工程(name string)。关系为:版本—contains–>组件, 组件------contains---->看护方式, 看护方式-------contains—>工程,
那在插入 看护方式_工厂_contains.csv时,rank不能既表示版本信息又表示组件信息,这种4个Tag组合关联的情况应该如何处理呢?

你文档没有看清楚它的说明,rank 是针对边类型的,你这里的看护方式应该是个点类型吧。两个不是一个概念。

可能是我表述不清晰,我举个例子:

schema:版本----contains----> 组件----contains---->看护方式----contains---->工程

  • 场景一
    版本1.0包含组件A版本2.0也包含组件A,但版本1.0包含的组件A只有一种看护方式(版本级),而版本2.0包含的组件A有两种看护方式(版本级 和 IDE级),对于这样的对应关系,如何通过插入边数据来表达出来呢? 上面您有提到使用rank加以区分,rank=1 表示版本1.0对应的边,rank=2表示版本2.0对应的边

  • 场景二
    版本1.0包含组件A版本2.0也包含组件A,但版本1.0包含的组件A只有一种看护方式(版本级),而版本2.0包含的组件A有两种看护方式(版本级 和 IDE级),在上述对应关系的基础上更进一步, 版本1.0组件A版本级看护方式 包含有甲、乙两个工程,而 版本2.0组件B版本级看护方式 只包含甲工程,这样的对应关系,又如何能表达出来呢?

图形化表述如下:

我明白你的意思了,:thinking: 那 rank 采用组合模式你觉得如何。rank 统一为 xyz,

  • x 为版本号,像你上面的版本 1.0 和 2.0 对应就是 1yz、2yz;
  • y 为看护方式,1 代表版本级,2 代表 IDE 级,像是版本 2.0 在 组件 A-看护方式 就是 rank 21z 和 22z;
  • z 为工程,甲乙丙丁各自对应 1234,那1.0 的组件看护方式含有甲、乙,就是 111 和 112;
  • 0 为默认值:如果没有看护方式或者是工程,就设定为 0;

参考下图(字打不下了,用手写了下);

感谢您提供的方案,我认为是行的通的。只是这样在 处理插入的数据时 和 根据rank查询某条路径时 复杂度就上去了。
我原本问这个问题的初衷 是 怀疑schema设计有问题,没想到存在这样复杂的设计问题。
我觉得这个问题的本质是因为 版本1.0版本2.0这两个点共用了组件A这个点,我原来想的解决方案是插入两个组件A如图所示 ,即两个不同的点 ,vid是不同的,属性name都是组件A,这样就不需要用到rank来区分边,只是会多一些冗余数据。您觉得这种方案可行吗? (不好意思,因为刚接触图数据库不久,不清楚业界的典型实践都是怎么做的,一上来就碰到这种怪问题,所以会怀疑自己的一些想法)
image

哦,你示意图中的 vid 是不同的诶,是不需要用到 rank 了。:thinking: 如果 vidA - vidB 之间有多条同类型的边,是可以用到 rank 的。

其实我觉得 rank xyz 的设定还有好处是,可以看到值就知道对应的包含(依赖关系)——当然这个是我觉得,我不懂工程业务。

我帮你喊个人看看 @MuYi 大佬你看看上面的 schema 设定是否合理呢?

想先问下,版本 1 的组件 A 和版本 2 的组件 A是一个东西吗?

版本 1 的组件 A 和版本 2 的组件 A
是一个东西的话,可以考虑 所有的边的RANK=1 的就是版本 1.0,RANK=2 的就是版本 2.0
如果不是相同的东西的话,可以考虑定义两个组件 A,一个是组件 A_1,一个是组件 A_2

是同一个东西。

大佬,请问一下使用rank的话,对于图中的场景二,您认为应该怎样处理比较好呢? 是建议按照@steam大佬上面推荐的组合模式设置rank值吗?

我觉得几条边可能是:
起点:看护方式(版本级)RANK:1 终点:工程(甲)
起点:看护方式(版本级)RANK:2 终点:工程(乙)
起点:看护方式(IDE 级)RANK:1 终点:工程(甲)

1 表示版本 1.0,2 表示版本 2.0

图中场景二有三条边,分别为 :

  1. 版本1.0组件A看护方式(版本级) 下部署了 工程甲。 rank = 11
  2. 版本1.0组件A看护方式(版本级) 下部署了 工程乙 。rank= 11
  3. 版本2.0组件B看护方式(IDE级) 下部署了 工程甲。 rank=22

为了区分这三条边,
第1条边的rank=11(第一个1表示版本1.0,第二个1表示组件A)。
第2条边的rank=11(第一个1表示版本1.0,第二个1表示组件A)。
第3条边的rank=22(第一个2表示版本2.0,第二个2表示组件B)。

您也是认为这样处理比较好吗? 因为除了表达版本信息,还有组件信息 。

此话题已在最后回复的 30 天后被自动关闭。不再允许新回复。