【问题标题】:TinkerPop/Graph: Traverse edge and then group by resulting vertex and traversed edgeTinkerPop/Graph:遍历边,然后按结果顶点和遍历边分组
【发布时间】:2018-06-20 16:17:48
【问题描述】:

举个例子:

marko = graph.addVertex(label, "person", id, 1, "name", "marko", "age", 29);
vadas = graph.addVertex(label, "person", id, 2, "name", "vadas", "age", 27);
josh = graph.addVertex(label, "person", id, 4, "name", "josh", "age", 32);
peter = graph.addVertex(label, "person", id, 5, "name", "peter", "age", 35);
lop = graph.addVertex(label, "software", id, 6, "name", "lop", "lang", "java");
ripple = graph.addVertex(label, "software", id, 7, "name", "ripple", "lang", "java");
tripple = graph.addVertex(label, "software", id, 8, "name", "tripple", "lang", "java");

marko.addEdge("created", lop, id, 9, "weight", 0.4f);
josh.addEdge("created", ripple, id, 10, "weight", 1.0f);
josh.addEdge("created", lop, id, 11, "weight", 0.4f);
peter.addEdge("created", lop, id, 12, "weight", 0.2f);
peter.addEdge("created", tripple, id, 13, "weight", 0.2f);
vadas.addEdge("created", tripple, id, 14, "weight", 0.2f);

我想从软件顶点lop和ripple开始,找到所有创建lop和ripple并且年龄超过32岁的人。然后我想按人分组,并在lop和ripple上创建权重。

所以我创造了一些东西,它给了我一个结果,但它看起来相当复杂:

g.V(6,7).as('soft').
in('created').has('age',gte(32)).
group()
by()
by(
  outE().where(
    inV().where(eq('soft'))
  ).fold())
.unfold()

==>v[4]=[e[11][4-created->6], e[10][4-created->7]]
==>v[5]=[e[12][5-created->6]]

另外,我希望最终结果具有与此类似的结构(对不起,如果我没有正确理解语法):

==>v[4,person,josh,32]=[lop=0.4, ripple=1.0]
==>v[5,person,peter,35]=[lop=0.2]

所以我需要完整的人顶点及其所有内容以及导致 lop 和波纹的所有边的列表。

json 表示形式如下:

[{
        "id": 4,
        "label": "person",
        "name": "josh",
        "age": "32",
        "software": [{
                "name": "lop",
                "weigth": 0.4
            },
            {
                "name": "ripple",
                "weigth": 1.0
            }
        ]
    },
    {
        "id": 5,
        "label": "person",
        "name": "peter",
        "age": "35",
        "software": [{
            "name": "lop",
            "weigth": 0.2
        }]
    }
]

【问题讨论】:

    标签: graph gremlin tinkerpop3


    【解决方案1】:

    有趣的问题。我认为更复杂的部分是转换为您想要的形式,而不是实际的数据检索。你的检索方法很好,虽然我是这样写的:

    gremlin> g.V(6,7).
    ......1>   inE('created').as('e').outV().has('age',gte(32)).as('p').
    ......2>   group().
    ......3>    by(select('p')).
    ......4>    by(select('e').fold()).
    ......5>   unfold()
    ==>v[4]=[e[11][4-created->6], e[10][4-created->7]]
    ==>v[5]=[e[12][5-created->6]]
    

    我认为这更容易阅读,因为很明显,您是从遍历路径中选择这些元素然后对它们进行操作,而不是使用遍历路径中的元素进行过滤。但是,它是否更好,还有待商榷。看到获得此初始输出的另一种方法并不会让我感到惊讶,但这就是我首先想到的。

    真正的问题是如何将该输出转换为您要求的预期形式,为此我采用了这种方法:

    gremlin> g.V(6,7).
    ......1>   inE('created').as('e').outV().has('age',gte(32)).as('p').
    ......2>   group().
    ......3>    by(select('p')).
    ......4>    by(select('e').fold()).
    ......5>   unfold().
    ......6>   project('id','label','name','age','software').
    ......7>     by(select(keys).id()).
    ......8>     by(select(keys).label()).
    ......9>     by(select(keys).values('name')).
    .....10>     by(select(keys).values('age')).
    .....11>     by(select(values).
    .....12>        unfold().
    .....13>        project('name','weight'). 
    .....14>          by(inV().values('name')).
    .....15>          by('weight').
    .....16>        fold())
    ==>[id:4,label:person,name:josh,age:32,software:[[name:lop,weight:0.4],[name:ripple,weight:1.0]]]
    ==>[id:5,label:person,name:peter,age:35,software:[[name:lop,weight:0.2]]]
    

    我只是使用project() 将展开的“人”顶点和边列表的Map 转换为所需的结构。请注意project() 的最后一个by(),因为它需要自己嵌入的project() 来处理原始Map 值中展开的边列表。关键在于fold() 将这些转换后的边缘返回到List,以便它们都被考虑在内(否则by() 只会处理第一个)。

    您可以在Gremlin Recipes 中阅读有关集合操作的更多信息。

    【讨论】:

    • 谢谢!很好,您如何在组之前使用 select 。这确实使它更具可读性。
    • 您实际上不需要select('p','e') 之前的group()。在by() 调制器中执行select() 就足够了。更新了我的答案
    猜你喜欢
    • 1970-01-01
    • 2016-07-08
    • 2020-07-07
    • 2021-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-15
    • 1970-01-01
    相关资源
    最近更新 更多