Gremlin找到最高的匹配

时间:2019-07-07 12:38:38

标签: gremlin tinkerpop tinkerpop3 amazon-neptune

我计划使用可以与Gremlin一起查询的图形数据库(AWS Neptune),作为一种知识库。 KB将用作具有多个功能的实体的分类工具。为简单起见,在此示例中,我使用几何形状编码实体的属性。假设我要对与正方形,三角形和圆形有关的点进行分类。我已将点与可能的正方形,三角形和圆形的不同可能关系绘制成图表,如下图所示。

enter image description here

创建于:


g.addV('Square').property(id, 'S_A')
 .addV('Square').property(id, 'S_B')
 .addV('Circle').property(id, 'C_A')
 .addV('Triangle').property(id, 'T_A')
 .addV('Triangle').property(id, 'T_B')
 .addV('Point').property(id, 'P1')
 .addV('Point').property(id, 'P2')
 .addV('Point').property(id, 'P3')

g.V('P1').addE('Has_Triangle').to(g.V('T_B'))
g.V('P2').addE('Has_Triangle').to(g.V('T_A'))
g.V('P1').addE('Has_Square').to(g.V('S_A'))
g.V('P2').addE('Has_Square').to(g.V('S_A'))
g.V('P2').addE('Has_Circle').to(g.V('C_A'))
g.V('P3').addE('Has_Circle').to(g.V('C_A'))
g.V('P3').addE('Has_Square').to(g.V('S_B'))


不同的实体例如是点,正方形,三角形,圆形。

所以我的最终目标是找到满足最高条件的点。例如

g.V().hasLabel('Point').where(and(
    out('Has_Triangle').hasId('T_A'),
    out('Has_Circle').hasId('C_A'),
    out('Has_Square').hasId('S_A')
))

// ==>v[P2]

上面的查询非常适用于将具有属性(T_A,S_A,C_A)的Point(a)分别分类为Point 2(P2)类型。但是,如果我必须使用相同的查询对具有属性(C_A,S_B,T_X)的Point进行分类,例如:

g.V().hasLabel('Point').where(and(
    out('Has_Triangle').hasId('T_X'),
    out('Has_Circle').hasId('C_A'),
    out('Has_Square').hasId('S_B')
))

该查询将无法将该点分类为点3(P3),因为在KB中Triangle没有已知的P3属性。

有没有一种方法可以表达一个查询,该查询返回具有最高 match 的顶点(在这种情况下为P3)?

谢谢。

编辑

到目前为止,解决此问题的最佳方法是为不存在的KB属性设置前哨值。然后修改查询以匹配每个确切的属性或标记值。但这意味着如果我将来在Point中添加新的“类型”属性,例如一个点Has_Hexagon,比我需要向图形的所有点添加前哨六角形。

编辑2

添加了创建示例数据的Gremlin脚本

1 个答案:

答案 0 :(得分:3)

您可以使用choose()步骤为每个匹配项增加一个计数器(sack),然后按计数器值排序(降序)并选择第一个(最高匹配项)。

gremlin> g.withSack(0).V().hasLabel('Point').
           choose(out('Has_Triangle').hasId('T_A'), sack(sum).by(constant(1))).
           choose(out('Has_Circle').hasId('T_A'),   sack(sum).by(constant(1))).
           choose(out('Has_Square').hasId('T_A'),   sack(sum).by(constant(1))).
           order().
             by(sack(), decr).
           limit(1)
==>v[P2]

gremlin> g.withSack(0).V().hasLabel('Point').
           choose(out('Has_Triangle').hasId('T_X'), sack(sum).by(constant(1))).
           choose(out('Has_Circle').hasId('T_A'),   sack(sum).by(constant(1))).
           choose(out('Has_Square').hasId('S_B'),   sack(sum).by(constant(1))).
           order().
             by(sack(), decr).
           limit(1)
==>v[P3]

以上查询中的每个choose()步骤都可以读为if (condition) increment-counter。无论如何,无论条件是否满足,Point步骤都会发出原始顶点(choose)。