TinkerPop/Graph:遍历边然后按结果顶点和遍历的边分组

TinkerPop/Graph: Traverse edge and then group by resulting vertex and traversed edge

给出以下示例:

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]

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

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
        }]
    }
]

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

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()将"person"顶点和边列表的展开Map转换为所需的结构。请注意 project() 的最终 by(),因为它需要自己的嵌入式 project() 来处理原始 Map 值中展开的边列表。关键是 fold() 将那些转换后的边返回到 List 以便它们都被考虑在内(否则 by() 只会处理第一个)。

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