在 Gremlin 中聚合和缩放一组顶点之间的多条边
Aggregating and Scaling multiple edges between a set of vertices in Gremlin
我有一个图表,我正尝试根据访问边缘的时间戳过滤:
我可以运行一个在少量数据上运行良好的查询,根据时间戳获取所有访问边,然后映射出 A、B、C、D、E、F。我运行遇到了 2 个我不确定如何解决的问题:
1- Scale(gremlify 上的查询 1),我可以在访问上有数千条边,所以说我 运行 查询我得到 10000 条边,还有 in/out V,即使在这种情况下输入输出的集合非常有限,但我似乎无法在不丢失 C、D、E、F 上的一些数据的情况下对它们进行重复数据删除。
g.E().hasLabel('access').
has('timestamp', between(3, 5)).as('access').
outV().hasLabel('B').as('b').
inE('belongs').
as('belongs').
outV().as('c').
inE('forms').as('forms').
outV().hasLabel('D', 'E', 'F').
as('element').
select('access').
inV().as('a').
select(
'a',
'access',
'b',
'belongs',
'c',
'forms',
'element'
).by(valueMap(true))
2- 聚合(gremlify 上的查询 2),在访问边缘我有一个 属性“结果”,它可以有多个值。我试过汇总 A 和 C 之间的结果(可能有很多 B,但大多数时候我不需要它们)但是当我这样做时,它似乎采用了图表的完整汇总,而不仅仅是在这两个顶点之间
g.E().hasLabel('access').
has('timestamp', between(3, 5)).as('access').
outV().hasLabel('B').as('b').
inE('belongs').
as('belongs').
outV().as('c').
inE('forms').as('forms').
outV().hasLabel('D', 'E', 'F').
as('element').
select('access').
inV().as('a').
project(
'a',
'belongs',
'c',
'forms',
'element',
'outcome'
).by(coalesce(
select('a').
label(),
constant('default')
)).
by(coalesce(
select('belongs').
label(),
constant('default')
)).
by(coalesce(
select('c').
label(),
constant('default')
)).
by(coalesce(
select('forms').
label(),
constant('default')
)).
by(coalesce(
select('element').
label(),
constant('default')
)).
by(select('access').
groupCount().
by(select('access').
values('outcome')))
在这种情况下,它总是returns所有边的nok值,并且该值始终为1(基本上是边的数量,而不是顶点之间的边的聚合)
{
"nok": 1
}
沙盒:
https://gremlify.com/1bos0bj1h03i/4
我很确定我遗漏了什么是我对 tinkerpop 的理解,任何指示都会很棒!
关于第 1 部分,您可以尝试从以下内容开始构建查询:
g.V().hasLabel('A').local(__.inE('access').order.by('timestamp', desc).limit(1))
至于第 2 部分,您没有明确说明要聚合什么以及如何聚合(隐式:groupCount)。最好是关于 SO 的单独问题。可能您需要一个 count() 步骤来计算单个顶点上的 属性 个值,并需要一个 sack() 步骤来沿遍历聚合它们。
发生了什么(我认为,这是基于对 gremlin 引擎的观察和有限知识)。每一步都会尝试查看图中的每条边(在我的测试环境中为 20k),因此目标是尝试尽可能减少起始节点集。
我想做的另一个想法是在 group() 内部做项目,但它似乎仍在处理所有边缘,直到你离开组。我不确定它是如何工作的,但是 运行 组之后的项目将 20k 遍历减少到 75。
我最后做的是:
- 查询所有“A”并按标签过滤
- 然后应用过滤器来减少集合 (
filter(has('timestamp', between(1, 2)))
)
- 然后按“a”节点对访问边进行分组,然后计算结果字段以创建我的聚合:
group().
by(select('a')).
by(
group().
by(outV().in('belongs')).
by(groupCount().
by(values('outcome'))))
这样做会显着减少遍历的边数。
从那里我做出了我的预测等...来格式化我的回复。
将查询时间从:
>TOTAL - - 91957.436 -
收件人:
>TOTAL - - 960.994 -
具有工作代码的游乐场:https://gremlify.com/8pifxw2uws5/1
我有一个图表,我正尝试根据访问边缘的时间戳过滤:
我可以运行一个在少量数据上运行良好的查询,根据时间戳获取所有访问边,然后映射出 A、B、C、D、E、F。我运行遇到了 2 个我不确定如何解决的问题:
1- Scale(gremlify 上的查询 1),我可以在访问上有数千条边,所以说我 运行 查询我得到 10000 条边,还有 in/out V,即使在这种情况下输入输出的集合非常有限,但我似乎无法在不丢失 C、D、E、F 上的一些数据的情况下对它们进行重复数据删除。
g.E().hasLabel('access').
has('timestamp', between(3, 5)).as('access').
outV().hasLabel('B').as('b').
inE('belongs').
as('belongs').
outV().as('c').
inE('forms').as('forms').
outV().hasLabel('D', 'E', 'F').
as('element').
select('access').
inV().as('a').
select(
'a',
'access',
'b',
'belongs',
'c',
'forms',
'element'
).by(valueMap(true))
2- 聚合(gremlify 上的查询 2),在访问边缘我有一个 属性“结果”,它可以有多个值。我试过汇总 A 和 C 之间的结果(可能有很多 B,但大多数时候我不需要它们)但是当我这样做时,它似乎采用了图表的完整汇总,而不仅仅是在这两个顶点之间
g.E().hasLabel('access').
has('timestamp', between(3, 5)).as('access').
outV().hasLabel('B').as('b').
inE('belongs').
as('belongs').
outV().as('c').
inE('forms').as('forms').
outV().hasLabel('D', 'E', 'F').
as('element').
select('access').
inV().as('a').
project(
'a',
'belongs',
'c',
'forms',
'element',
'outcome'
).by(coalesce(
select('a').
label(),
constant('default')
)).
by(coalesce(
select('belongs').
label(),
constant('default')
)).
by(coalesce(
select('c').
label(),
constant('default')
)).
by(coalesce(
select('forms').
label(),
constant('default')
)).
by(coalesce(
select('element').
label(),
constant('default')
)).
by(select('access').
groupCount().
by(select('access').
values('outcome')))
在这种情况下,它总是returns所有边的nok值,并且该值始终为1(基本上是边的数量,而不是顶点之间的边的聚合)
{
"nok": 1
}
沙盒: https://gremlify.com/1bos0bj1h03i/4
我很确定我遗漏了什么是我对 tinkerpop 的理解,任何指示都会很棒!
关于第 1 部分,您可以尝试从以下内容开始构建查询:
g.V().hasLabel('A').local(__.inE('access').order.by('timestamp', desc).limit(1))
至于第 2 部分,您没有明确说明要聚合什么以及如何聚合(隐式:groupCount)。最好是关于 SO 的单独问题。可能您需要一个 count() 步骤来计算单个顶点上的 属性 个值,并需要一个 sack() 步骤来沿遍历聚合它们。
发生了什么(我认为,这是基于对 gremlin 引擎的观察和有限知识)。每一步都会尝试查看图中的每条边(在我的测试环境中为 20k),因此目标是尝试尽可能减少起始节点集。
我想做的另一个想法是在 group() 内部做项目,但它似乎仍在处理所有边缘,直到你离开组。我不确定它是如何工作的,但是 运行 组之后的项目将 20k 遍历减少到 75。
我最后做的是:
- 查询所有“A”并按标签过滤
- 然后应用过滤器来减少集合 (
filter(has('timestamp', between(1, 2)))
) - 然后按“a”节点对访问边进行分组,然后计算结果字段以创建我的聚合:
group().
by(select('a')).
by(
group().
by(outV().in('belongs')).
by(groupCount().
by(values('outcome'))))
这样做会显着减少遍历的边数。
从那里我做出了我的预测等...来格式化我的回复。
将查询时间从:
>TOTAL - - 91957.436 -
收件人:
>TOTAL - - 960.994 -
具有工作代码的游乐场:https://gremlify.com/8pifxw2uws5/1