【问题标题】:How to get a list of most similar vertexes given an array of references in gremlin给定gremlin中的引用数组,如何获取最相似顶点的列表
【发布时间】:2026-02-20 03:45:01
【问题描述】:

给定这样的图表:


其中 A,B,C... 比方说书籍,边表示两本书相似,相似程度用边中的数字表示。边缘的方向无关紧要。

给定 N 个引用,我想通过求和连接的相似度数来检索最相似的直接连接边,按最相似的第一个排序且不重复,不包括引用。

在上面的例子中,给定 A 和 B,我们会返回

F, 50
D, 45
E, 31
C, 30
G, 3

您能提供一些有关查询的帮助吗?这是我认为它应该看起来的样子,但没有运气:

g.V('A','B').as('references').bothV().bothE().where(neq('references')).group('id').by('similarity',sum()).order().by('sum_similarity',desc)

【问题讨论】:

    标签: gremlin azure-cosmosdb-gremlinapi


    【解决方案1】:

    这是执行此操作的查询:

    g.V().has('name', within(['A','B'])).as('references')
    .bothE().as('e').otherV()
    .group().by('name').by(select('e').values('similarity').sum())
    .unfold().order().by(values, desc)
    

    说明:

    第一行使用within按“名称”选择参考顶点。

    第二行遍历到最近的邻居,同时保持对边缘的引用。

    第三行按“名称”作为键对顶点进行分组,将引用边的总和“相似度”作为值。

    最后一行使用unfold 反汇编地图,并按值降序排列。

    【讨论】:

    • 谢谢! order().by(values,desc) 在 azure CosmoDB 上不起作用,我需要以不同的方式实现引用的删除;所以我的最终结果是: g.V('A','B').bothE().as('e').otherV().has('id', without('A','B') ).group().by('id').by(select('e').values('similarity').sum()).unfold().order().by(values,decr).limit (3)
    • 感谢您接受我的回答。至于 order by,在 4.3.x 版本中不推荐使用 incr 和 decr,取而代之的是更标准的 asc 和 desc。可能 CosmosDB 仍与旧版本保持一致。
    【解决方案2】:

    Kfir 可能会起作用,但它不会考虑缺少 similarity 属性(考虑到“A”和“B”之间的边缘,这似乎是可能的)。此外,您无需使用任何可启用路径跟踪的步骤。

    让我们从你的图表开始:

    g = TinkerGraph.open().traversal()
    g.addV().property(id, 'A').as('A').
      addV().property(id, 'B').as('B').
      addV().property(id, 'C').as('C').
      addV().property(id, 'D').as('D').
      addV().property(id, 'E').as('E').
      addV().property(id, 'F').as('F').
      addV().property(id, 'G').as('G').
      addV().property(id, 'H').as('H').
      addV().property(id, 'J').as('J').
      addE('similarTo').from('A').to('C').property('similarity', 30).
      addE('similarTo').from('D').to('A').property('similarity', 20).
      addE('similarTo').from('E').to('A').property('similarity', 10).
      addE('similarTo').from('B').to('A').
      addE('similarTo').from('B').to('D').property('similarity', 25).
      addE('similarTo').from('B').to('E').property('similarity', 21).
      addE('similarTo').from('F').to('B').property('similarity', 50).
      addE('similarTo').from('G').to('B').property('similarity', 3).
      addE('similarTo').from('F').to('H').property('similarity', 80).
      addE('similarTo').from('H').to('J').property('similarity', 5).
      addE('similarTo').from('J').to('F').property('similarity', 11).iterate()
    

    现在,将缺失属性考虑在内并仅使用不需要路径跟踪的步骤的查询将是:

    gremlin> g.V('A','B','C').
             union(outE('similarTo').sack(assign).
                                       by(coalesce(values('similarity'),
                                                   constant(0))).inV(),
                   inE('similarTo').sack(assign).
                                      by(coalesce(values('similarity'),
                                                  constant(0))).outV()).
             hasId(without('A','B', 'C')).
             group().
               by().
               by(sack().sum()).
             order(local).
               by(values, desc).
             limit(local, 3).next()
    ==>v[F]=50
    ==>v[D]=45
    ==>v[E]=31
    

    结果是包含 3 个最相似顶点及其各自相似度分数的地图。

    【讨论】:

    • 对不起哥们,我从您的查询中学到了很多,但是我错误地在A和B之间添加了“相似性”节点,如果它们不相似,就不会有任何边缘跨度>
    最近更新 更多