Я новичок в Gremlin и графических базах данных в целом. Мне было поручено составить план выполнения задачи на основе глубины, на которой узел существует в подграфе.

Пока что я могу создать подграф и список путей на основе этого подграфа. Я застрял, когда пытаюсь добавить глубины к путям, особенно когда некоторые узлы существуют на нескольких путях. Вы можете увидеть здесь график, на котором я тестирую:

public void generateTestGraph(){
    Vertex web  = this.sqlgGraph.addVertex(T.label, "Server", "name", "WEB");
    Vertex app  = this.sqlgGraph.addVertex(T.label, "Server", "name", "APP1");
    Vertex app2 = this.sqlgGraph.addVertex(T.label, "Server", "name", "APP2");
    Vertex app3 = this.sqlgGraph.addVertex(T.label, "Server", "name", "APP3");
    Vertex sql  = this.sqlgGraph.addVertex(T.label, "Server", "name", "SQL");
    web.addEdge("DEPENDS_ON", app);
    web.addEdge("DEPENDS_ON", app2);
    app.addEdge("DEPENDS_ON", sql);
    app3.addEdge("DEPENDS_ON", sql);
    app2.addEdge("DEPENDS_ON", app3);

    this.sqlgGraph.tx().commit();
}

Я могу создавать такие списки путей:

public void testDepGraph(){
    String name = "SQL";

    Graph subGraph = (Graph) this.sqlgGraph.traversal().V().has("name", name).repeat(__.inE("DEPENDS_ON")
    .subgraph("subGraph").outV()).in("DEPENDS_ON").loops().is(P.gt(50)).cap("subGraph").next();

    Object vl = subGraph.traversal().V().has("name", name).repeat(__.in("DEPENDS_ON")).emit(__.not(__.inE())).path().by("name").toList();
}

Но они выглядят так:

{
    ["SQL", "APP1", "WEB"],
    ["SQL", "APP3", "APP2", "WEB"]
}

Это близко, но я бы хотел, чтобы результат выглядел так:

{
    0: {"SQL"},
    1: {"APP1", "APP3"},
    2: {"APP2"},
    3: {"WEB"}
}

Итак, мой вопрос: могу ли я получить желаемые результаты, используя Gremlin напрямую, или мне придется выполнять некоторую постобработку вручную (код)?

0
BaKeR 28 Июн 2017 в 22:19

1 ответ

Лучший ответ

Это можно сделать с помощью одного запроса, но это довольно сложно и может быть трудно понять, если вы только начали использовать Gremlin.

gremlin> g.V().group("x").
                 by("name").
                 by(out("DEPENDS_ON").values("name").fold()).
           barrier().
           repeat(
             cap("x").unfold().
             filter(select(values).not(unfold().where(without("y")))).
                    select(keys).where(without("y")).
             aggregate("y").
             aggregate("z").
               by(project("a","b").
                    by().
                    by(coalesce(select("z").unfold().select("b").order().by(decr).limit(1).
                                  sack(assign).sack(sum).by(constant(1)).sack(),
                                constant(0))))
           ).cap("z").unfold().group().by(select("b")).by(select("a").fold())
==>[0:[SQL],1:[APP3,APP1],2:[APP2],3:[WEB]]

Этот запрос создает карту зависимостей x, а затем просматривает карту, выбирая только те записи, которые имеют зависимости от компонентов, которые были обработаны в предыдущих итерациях. repeat() прекратит работу, как только не останется необработанных компонентов. После каждой итерации обработанные компоненты будут сохранены в списке с именем y, и тот же компонент будет сохранен в виде кортежа (вместе с индексом итерации) в списке с именем z.

Список с именем z в конечном итоге будет использоваться для создания желаемого результата карты, где индекс итерации является ключом карты, а компоненты - соответствующими значениями.

4
Daniel Kuppitz 3 Ноя 2017 в 23:18
Это потрясающе. Спасибо.
 – 
BaKeR
5 Июл 2017 в 18:10
, Я наконец-то пришел к реализации вашего ответа, но, хоть убей, я не могу преобразовать его в синтаксис JAVA. Сможете ли вы указать мне куда-нибудь или помочь мне? Если нужно, я могу задать новый вопрос. Спасибо.
 – 
BaKeR
2 Ноя 2017 в 21:54
Дэниел, это потрясающе. Так много статического импорта ... Еще раз спасибо.
 – 
BaKeR
2 Ноя 2017 в 22:25