当前位置: 首页 > 知识库问答 >
问题:

Tinkerpop Gremlin-如何将变量聚合到遍历独立集合中

上官华池
2023-03-14

我目前正在阅读《从业者图形数据指南》,并试图解决以下问题(仅用于学习目的)。以下是books movie数据集的上下文,在本例中,该数据集使用“标记”顶点、“movie”顶点和“额定”边,其额定属性为1-5。

为了练习,并扩展我对书中概念的理解,我想让所有电影都标记为“喜剧”,并计算平均NP。为此,我想将所有正(1)和中性或负(-1)评级汇总到一个列表中。然后我想把这些值的总和除以这个列表中变量的数量(平均值)。这就是我所尝试的:

dev.withSack{[]}{it.clone()}.    // create a sack with an empty list that clones when split
V().has('Tag', 'tag_name', 'comedy').
    in('topic_tagged').as('film').    // walk to movies tagged as comedy
    inE('rated').    // walk to the rated edges
        choose(values('rating').is(gte(3.0)),
            sack(addAll).by(constant([1.0])),
            sack(addAll).by(constant([-1.0]))).    // add a value or 1 or -1 to this movies list, depending on the rating
    group().
        by(select('film').values('movie_title')).
        by(project('a', 'b').
            by(sack().unfold().sum()).    // add all values from the list
            by(sack().unfold().count()).    // Count the values in the list
            math('a / b')).
    order(local).
        by(values, desc)

这最终导致每部电影要么是“1.0”,要么是“-1.0”。

"Journey of August King The (1995)": "1.0",
"Once Upon a Time... When We Were Colored (1995)": "1.0", ...

在我的测试中,这些值似乎没有像我预期的那样聚合到集合中。我尝试了各种方法,但都没有达到我的预期结果。

我知道我可以通过对初始值为“0.0”的sack进行加减,然后除以边缘计数来实现这个结果,但我希望通过使用列表并避免对边缘进行额外遍历来获得计数,从而获得更有效的解决方案。

使用列表可以实现我的结果吗?如果是,如何?

编辑1:

下面的代码简单得多,取自Kelvins示例,只需使用折叠步骤即可聚合每个评级:

dev.V().
    has('Tag', 'tag_name', 'comedy').
        in('topic_tagged').
        project('movie', 'result').
            by('movie_title').
            by(inE('rated').
                choose(values('rating').is(gte(3.0)),
                    constant(1.0),
                    constant(-1.0)).
                fold())    // replace fold() with mean() to calculate the mean, or do something with the collection

我觉得有点尴尬,我完全忘记了折叠步骤,因为折叠和展开是如此常见。我想是想得太多了。

共有1个答案

柳项明
2023-03-14

您可以考虑使用聚合而不是sack的不同方法。您还可以使用均值步骤来避免需要数学步骤。由于我没有你的数据,我举了一个例子,在你的案例中使用了航空路线数据集,并使用机场标高而不是电影评分。

gremlin> g.V().hasLabel('airport').limit(10).values('elev')
==>1026
==>151
==>542
==>599
==>19
==>143
==>14
==>607
==>64
==>313  

使用和你类似的加权系统

gremlin> g.V().hasLabel('airport').limit(10).
......1>   choose(values('elev').is(gt(500)),
......2>     constant(1),
......3>     constant(-1))
==>1
==>-1
==>1
==>1
==>-1
==>-1
==>-1
==>1
==>-1
==>-1    

这些结果可以聚合成一个大容量集

gremlin> g.V().hasLabel('airport').limit(10).
......1>   choose(values('elev').is(gt(500)),
......2>     constant(1),
......3>     constant(-1)).
......4>   aggregate('x').
......5>   cap('x')
==>[1,1,1,1,-1,-1,-1,-1,-1,-1]  

从那里我们可以得到平均值

gremlin> g.V().hasLabel('airport').limit(10).
......1>   choose(values('elev').is(gt(500)),
......2>     constant(1),
......3>     constant(-1)).
......4>   aggregate('x').
......5>   cap('x').
......6>   unfold().
......7>   mean()
==>-0.2    

现在,这当然是人为的,因为您通常不会执行聚合('x'). cap('x'). unfol(). means(),您只需使用means()本身。但是使用这种模式,您应该能够解决您的问题。

编辑以添加

仔细考虑一下,您可能甚至不需要聚合就可以编写查询-类似于这样(下图)。我使用空中路线距离边缘属性来模拟类似于您的查询的东西。该示例只是使用一个机场来保持简单。首先只是创建分数列表...

gremlin> g.V().has('airport','code','SAF').
......1>   project('airport','mean').
......2>     by('code').
......3>     by(outE().
......4>        choose(values('dist').is(gt(350)),
......5>          constant(1),
......6>          constant(-1)).
......7>          fold())
==>[airport:SAF,mean:[1,1,1,-1]]   

最后创造平均值

gremlin> g.V().has('airport','code','SAF').
......1>   project('airport','mean').
......2>     by('code').
......3>     by(outE().
......4>        choose(values('dist').is(gt(350)),
......5>          constant(1),
......6>          constant(-1)).
......7>          mean())
==>[airport:SAF,mean:0.5]

再次编辑

如果edge属性可能不存在,您可以这样做...

gremlin> g.V().has('airport','code','SAF').
......1>   project('airport','mean').
......2>     by('code').
......3>     by(outE().
......4>        coalesce(values('x'),constant(100)).
......5>        choose(identity().is(gt(350)),
......6>          constant(1),
......7>          constant(-1)).
......8>          fold())
==>[airport:SAF,mean:[-1,-1,-1,-1]]  
 类似资料:
  • Map 集合的遍历与 List 和 Set 集合不同。Map 有两组值,因此遍历时可以只遍历值的集合,也可以只遍历键的集合,也可以同时遍历。Map 以及实现 Map 的接口类(如 HashMap、TreeMap、LinkedHashMap、Hashtable 等)都可以用以下几种方式遍历。 1)在 for 循环中使用 entries 实现 Map 的遍历(最常见和最常用的)。 2)使用 for-e

  • 《 Java Iterator遍历Collection集合元素》一节中主要讲解如何使用 Iterator 接口迭代访问 Collection 集合里的元素,除了这个方法之外,我们还可以使用 Java 5 提供的 foreach 循环迭代访问集合元素,而且更加便捷。如下程序示范了使用 foreach 循环来迭代访问集合元素。 输出结果为: 小牛知识库C++教程 小牛知识库C语言教程 小牛知识库Jav

  • 集合的遍历 在程序开发中,经常需要遍历集合中的所有元素。针对这种需求,JDK专门提供了一个接口Iterator。Iterator接口也是Java集合中的一员,但它与Collection、Map接口有所不同,Collection接口与Map接口主要用于存储元素,而Iterator主要用于迭代访问(即遍历)Collection中的元素,因此Iterator对象也被称为迭代器。 Iterator迭代器对

  • Java 8 为 Iterable 接口新增了一个 forEach(Consumer action) 默认方法,该方法所需参数的类型是一个函数式接口,而 Iterable 接口是 Collection 接口的父接口,因此 Collection 集合也可直接调用该方法。 当程序调用 Iterable 的 forEach(Consumer action) 遍历集合元素时,程序会依次将集合元素传给 Co

  • 运行此代码时: 引发异常: 系统。无效操作异常:集合被修改;枚举操作可能无法执行。 怎么做。NET知道该集合在枚举器迭代该集合时被修改了吗?集合对象中是否有此标志?

  • 问题内容: 说我有一个数组。如何一次迭代两个? 问题答案: 您可以使用称为stride(to :, by :)的进度循环,每n个元素对元素进行一次迭代: Xcode 8.3.2•Swift 3.1