【问题标题】:Gremlin - finding connected nodes with several boolean conditions on both nodes and edges propertiesGremlin - 在节点和边属性上查找具有多个布尔条件的连接节点
【发布时间】:2020-08-05 13:32:54
【问题描述】:

我想找到应该链接到给定节点的节点,其中链接由一些逻辑定义,该逻辑使用节点和现有边的属性,逻辑如下:

A)(该对具有相同的 zip(节点属性)和 name_similarity(边缘属性)> 0.3 OR

B) 该对具有不同的 zip 和 name_similarity > 0.5 OR

C) 该对的边缘类型为“external_info”,值为“connect”)

D) AND(该对没有带有“external info”且值为“disconnect”的边类型)

简而言之: (A | B | C) & (~D)

我还是 gremlin 的新手,所以我不确定如何在边和节点上组合多个条件。

以下是创建图表的代码,以及该图表的预期结果:

# creating nodes

(g.addV('person').property('name', 'A').property('zip', '123').
addV('person').property('name', 'B').property('zip', '123').
addV('person').property('name', 'C').property('zip', '456').
addV('person').property('name', 'D').property('zip', '456').
addV('person').property('name', 'E').property('zip', '123').
addV('person').property('name', 'F').property('zip', '999').iterate())

node1 = g.V().has('name', 'A').next()
node2 = g.V().has('name', 'B').next()
node3 = g.V().has('name', 'C').next()
node4 = g.V().has('name', 'D').next()
node5 = g.V().has('name', 'E').next()
node6 = g.V().has('name', 'F').next()

# creating name similarity edges

g.V(node1).addE('name_similarity').from_(node1).to(node2).property('score', 1).next() # over threshold
g.V(node1).addE('name_similarity').from_(node1).to(node3).property('score', 0.2).next() # under threshold
g.V(node1).addE('name_similarity').from_(node1).to(node4).property('score', 0.4).next() # over threshold
g.V(node1).addE('name_similarity').from_(node1).to(node5).property('score', 1).next() # over threshold
g.V(node1).addE('name_similarity').from_(node1).to(node6).property('score', 0).next() # under threshold

# creating external output edges

g.V(node1).addE('external_info').from_(node1).to(node5).property('decision', 'connect').next() 
g.V(node1).addE('external_info').from_(node1).to(node6).property('decision', 'disconnect').next() 

输入节点 A 的预期输出是节点 B(由于条件 A)、D(由于条件 B)和 F(由于条件 C)。由于条件 D,节点 E 不应链接。

我正在寻找可以检索这些结果的 Gremlin 查询。

【问题讨论】:

    标签: gremlin graph-databases gremlinpython


    【解决方案1】:

    鉴于您预期的输出,您的数据似乎有问题,因此我不得不进行更正:

    • 顶点 D 不会出现在结果中,因为“分数”小于 0.5
    • “external_info”边缘似乎颠倒了

    这是我使用的数据:

    g.addV('person').property('name', 'A').property('zip', '123').
    addV('person').property('name', 'B').property('zip', '123').
    addV('person').property('name', 'C').property('zip', '456').
    addV('person').property('name', 'D').property('zip', '456').
    addV('person').property('name', 'E').property('zip', '123').
    addV('person').property('name', 'F').property('zip', '999').iterate()
    node1 = g.V().has('name', 'A').next()
    node2 = g.V().has('name', 'B').next()
    node3 = g.V().has('name', 'C').next()
    node4 = g.V().has('name', 'D').next()
    node5 = g.V().has('name', 'E').next()
    node6 = g.V().has('name', 'F').next()
    g.V(node1).addE('name_similarity').from(node1).to(node2).property('score', 1).next() 
    g.V(node1).addE('name_similarity').from(node1).to(node3).property('score', 0.2).next() 
    g.V(node1).addE('name_similarity').from(node1).to(node4).property('score', 0.6).next() 
    g.V(node1).addE('name_similarity').from(node1).to(node5).property('score', 1).next() 
    g.V(node1).addE('name_similarity').from(node1).to(node6).property('score', 0).next() 
    g.V(node1).addE('external_info').from(node1).to(node6).property('decision', 'connect').next() 
    g.V(node1).addE('external_info').from(node1).to(node5).property('decision', 'disconnect').next() 
    

    我采用了以下方法:

    gremlin> g.V().has('person','name','A').as('a').
    ......1>   V().as('b').
    ......2>   where('a',neq('b')).
    ......3>   or(where('a',eq('b')).                                                    // A
    ......4>        by('zip').
    ......5>      bothE('name_similarity').has('score',gt(0.3)).otherV().where(eq('a')), 
    ......6>      bothE('name_similarity').has('score',gt(0.5)).otherV().where(eq('a')), // B
    ......7>      bothE('external_info').                                                // C
    ......8>        has('decision','connect').otherV().where(eq('a'))).
    ......9>   filter(__.not(bothE('external_info').                                     // D
    .....10>                 has('decision','disconnect').otherV().where(eq('a')))).
    .....11>   select('a','b').
    .....12>    by('name')
    ==>[a:A,b:B]
    ==>[a:A,b:D]
    ==>[a:A,b:F]
    

    我认为这包含您正在寻找的所有逻辑,但我没有花很多时间优化它,因为我认为任何优化都无法解决V().as('b') 的全图扫描带来的痛苦,因此,要么您的情况涉及一个相对较小的图形(可能在内存中)并且此查询将起作用,要么您需要一起找到另一种方法。也许您有进一步限制“b”的方法,这可能会有所帮助?如果沿着这些思路可行,我可能会尝试更好地定义边缘遍历的方向性以避免bothE(),而是限制为outE()inE(),这将摆脱otherV()。希望您使用允许以顶点为中心的索引的图表,这也可以加快“分数”上的边缘查找速度(不确定这是否对“决策”有很大帮助,因为它的选择性很低)。

    【讨论】:

    • 谢谢斯蒂芬! 1)根据您的问题,我打算在海王星图形数据库中使用它。这是我第一次使用图形数据库,所以我不确定“小”的定义是什么。我预计会有 间接链接到节点X的节点(通过相同的连接定义逻辑)
    • (跳数未知且无限制)
    • 我倾向于认为“小”是可以轻松放入内存的东西。我想说数十万条边可能对所有人来说都太小了,除了带有内存音调的最大机器。至于您的第二个问题,标记为 (2),我不确定您所说的“直接和间接链接到节点 X”是什么意思。
    • 假设一个新图,其中节点 A 连接到节点 B(比如条件 B,名称相似度 = 0.9);并且节点B连接到节点C(例如通过条件C,external_info),但节点A和C之间没有边。意思是A-B-C。我怎样才能使用你的遍历,所以给定节点A,我会得到节点 B 和 C? (以及连接到 B 和 C 的所有节点(如果存在))谢谢
    • 如果我之前在性能方面担心这种遍历,我会说为这种相似性逻辑添加无限数量的跃点会让我感觉更不自信。我有两个建议:(1)从您的生产规模图的性能角度验证我提供的内容是否适用于单跳,因为添加遍历更深的循环只会进一步增加成本并使遍历更加不可读。如果可能,在没有“间接”关系的情况下提高它的性能。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-01-15
    • 2021-01-24
    • 1970-01-01
    • 2023-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多