【问题标题】:Gremlin find highest matchGremlin 找到最高匹配
【发布时间】:2019-07-07 12:38:38
【问题描述】:

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

创建者:


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) 的点(a)分别分类为Point 2(P2)类型。但是,如果我必须使用相同的查询来对具有属性 (C_A,S_B,T_X) 的点进行分类,例如:

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 中,P3 没有已知的 Triangle 属性。

有没有一种方法可以表达一个查询,它返回具有最高 匹配 的顶点,在这种情况下是 P3?

提前谢谢你。

编辑

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

编辑 2

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

【问题讨论】:

标签: gremlin tinkerpop tinkerpop3 amazon-neptune


【解决方案1】:

您可以使用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。在任何情况下,无论条件是否满足,choose-step 都会发射原始顶点(Point)。

【讨论】:

  • 嗨,丹尼尔,感谢您的回复,除了一个用例之外,查询可以正常工作。如果某个点带有(T_A,S_A,C_B),则查询将返回P2,这不应该是这种情况,因为P2 有3 个三个条件。因此,我将对其进行修改以检查sack 总和是否与顶点的传出边数匹配。
猜你喜欢
  • 1970-01-01
  • 2017-01-21
  • 2014-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多