【问题标题】:Gremlin: Calculate division of based on two counts in one line of codeGremlin:根据一行代码中的两个计数计算除法
【发布时间】:2019-03-21 18:03:50
【问题描述】:

我有两个计数,计算如下:

1)g.V().hasLabel('brand').where(__.inE('client_brand').count().is(gt(0))).count()

2)g.V().hasLabel('brand').count()

我想得到一行代码,结果是第一个计数除以第二个计数。

【问题讨论】:

    标签: orientdb gremlin


    【解决方案1】:

    这是一种方法:

    g.V().hasLabel('brand').
      fold().as('a','b').
      math('a/b').
        by(unfold().where(inE('client_brand')).count())
        by(unfold().count())
    

    请注意,我将第一次遍历简化为 .where(inE('client_brand')).count(),因为您只需计算至少有一条边,无需全部计算并进行比较。

    你也可以union()点赞:

    g.V().hasLabel('brand').
      union(where(inE('client_brand')).count(),
            count())
      fold().as('a','b').
      math('a/b').
        by(limit(local,1))
        by(tail(local))
    

    虽然第一个更容易阅读/遵循,但我想第二个更好,因为它只存储两个计数的列表,而第一个存储所有“品牌”顶点的列表,这会更多我猜是内存密集型的。

    Daniel Kuppitz 提供的另一种方式,它以一种有趣的方式使用 groupCount()

    g.V().hasLabel('brand').
      groupCount().
        by(choose(inE('client_brand'),
                    constant('a'),
                    constant('b'))).
      math('a/(a+b)')
    

    以下使用sack() 步骤的解决方案说明了为什么我们有math() 步骤:

    g.V().hasLabel('brand').
      groupCount().
        by(choose(inE('client_brand'),
                    constant('a'),
                    constant('b'))).
      sack(assign).
        by(coalesce(select('a'), constant(0))).
      sack(mult).
        by(constant(1.0)). /* we need a double */
      sack(div).
        by(select(values).sum(local)).
      sack()
    

    如果你可以使用 lambda,那么:

    g.V().hasLabel('brand').
      union(where(inE('client_brand')).count(),
            count())
      fold().
      map{ it.get()[0]/it.get()[1]} 
    

    【讨论】:

    • 嗨,斯蒂芬,谢谢!不幸的是,当我尝试运行第一个错误时出现此错误: groovy.lang.MissingMethodException: No signature of method: org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal.math() 适用于参数类型:(java.lang.String) 值:[a/b] 可能的解决方案:max()、max(groovy.lang.Closure)、with(groovy.lang.Closure)、max(java.util.Comparator) , 每个(groovy.lang.Closure), 每个(groovy.lang.Closure)
    • 'brand'有属性name、id、description和entityNameType,入边'client_brand'和'client'有相同的属性。
    • math() 步骤是在 TinkerPop 3.3.0 中引入的 - 也许您使用的是旧版本? daniel kuppitz 提到了另一种使用math() step 的方法,我只是将其添加到我的答案中,因为他不想再添加一个。如果在您使用math() 解决问题后仍然无法正常工作,如果您还有其他问题需要解决,我建议提供一些示例数据:- 这是一个示例stackoverflow.com/questions/51388315/…
    【解决方案2】:

    这对我有用:

    g.V().limit(1).project('client_brand_count','total_brands')
    .by(g.V().hasLabel('brand')
    .where(__.inE('client_brand').count().is(gt(0))).count())
    .by(g.V().hasLabel('brand').count())
    .map{it.get().values()[0] / it.get().values()[1]}
    .project('brand_client_pct')
    

    【讨论】:

    • 嗯,你可以使用闭包,但它们应该是最后的手段,这就是为什么它们不是我的建议或 kuppitz 建议的一部分。闭包会降低代码的可移植性,因为它们并非在所有环境中都有效。我还认为,如果您仍打算使用 lambda,则可以大大降低您提出的解决方案的复杂性。我用应该更直接的 lambda 解决方案再次更新了我的答案。考虑在两者上做一个profile(),看看发生了什么不同。
    猜你喜欢
    • 2022-10-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-22
    相关资源
    最近更新 更多