TinkerPop / Graph: пройти по ребру, а затем сгруппировать по полученной вершине и пройденному ребру

В приведенном ниже примере:

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

person David K    schedule 20.06.2018    source источник


Ответы (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 списка вершин и ребер "человека" в желаемую структуру. Обратите внимание на последний by() этого project(), поскольку он требует своего собственного встроенного project() для работы с развернутым списком ребер в значениях исходного Map. Ключ в том, чтобы fold() вернуть эти преобразованные ребра в List, чтобы все они были учтены (иначе by() будет иметь дело только с первым).

Дополнительную информацию о манипуляциях с коллекциями можно найти в рецептах гремлин.

person stephen mallette    schedule 21.06.2018
comment
Спасибо! Приятно, как вы используете select перед группой. Это делает его более читабельным. - person David K; 22.06.2018
comment
На самом деле вам не нужен select('p','e') перед group(). выполнения select() внутри by() модуляторов достаточно. обновил свой ответ - person stephen mallette; 22.06.2018