В качестве начальной точки вам не нужен первый V
в вашем обходе. Вам просто нужно начать с inject()
. Если вы начнете с V()
, вы в конечном итоге выполните следующие шаги для каждой вершины графа.
Тем не менее, я не вижу проблемы с вашим обходом, и он работает нормально с TinkerGraph, как только я адаптировал его к современному графу игрушек:
gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> properties = [p1: "p1_value", p2: "p2_value"]
==>p1=p1_value
==>p2=p2_value
gremlin> g.inject(properties).as('props_label').
......1> V().has("name",'marko').as('from_label').
......2> V().has("name",'josh').as('to_label').
......3> coalesce(inE('knows').where(outV().as('from_label')),
......4> addE('knows').from('from_label').as('e_label').select('props_label').
......5> unfold().as('kv_label').select('e_label').
......6> property(select('kv_label').by(Column.keys),
......7> select('kv_label').by(Column.values)))
==>e[8][1-knows->4]
gremlin> g.inject(properties).as('props_label').
......1> V().has("name",'peter').as('from_label').
......2> V().has("name",'vadas').as('to_label').
......3> coalesce(inE('knows').where(outV().as('from_label')),
......4> addE('knows').from('from_label').as('e_label').select('props_label').
......5> unfold().as('kv_label').select('e_label').
......6> property(select('kv_label').by(Column.keys),
......7> select('kv_label').by(Column.values)))
==>e[13][6-knows->2]
==>e[13][6-knows->2]
Возможно, вы захотите dedup()
результаты этого обхода, так как вы получите один результат для каждого ключа свойства на карте, учитывая его unfold()
в строке 5.
Ошибка, которую вы получаете, является ошибкой на стороне сервера, а я нетдумаю проблема с gremlinpython. Это указывает на ситуацию, когда select('kv_label').by(Column.keys)
пытается получить доступ к объекту JanusGraph StandardVertex
. Я могу воссоздать эту проблему в TinkerGraph достаточно легко, учитывая ваш обновленный вопрос:
gremlin> g.addV("TestType").property("name", "1").
......1> addV("TestType").property("name", "2").
......2> inject(["p1": "v1", "p2": "v2"]).
......3> unfold().as("props").
......4> V().has("name", "1").as("from").
......5> V().has("name", "2").as("to").
......6> coalesce(inE("DEPENDS_ON").where(outV().as("from")),
......7> addE("DEPENDS_ON").from("from").
......8> property(select("props").by(keys), select("props").by(values))).dedup()
The provided object does not have accessible keys: class org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertex
Type ':help' or ':h' for help.
Display stack trace? [yN]n
Это очень отличается от исходного вопроса, поэтому я не смог его воссоздать. Вы ожидаете только пары ключ / значение от вашего inject()
в потоке, но на самом деле есть что-то еще:
gremlin> g.addV("TestType").property("name", "1").
......1> addV("TestType").property("name", "2").
......2> inject(["p1": "v1", "p2": "v2"]).
......3> unfold()
==>p1=v1
==>p2=v2
==>v[2]
Когда v[2]
пробивается к select("props").by(keys)
, вы получаете исключение Iописано. Вы можете исправить это, переместив inject()
в начало или используя withSideEffect()
gremlin> g.inject(["p1": "v1", "p2": "v2"]).as('props').
......1> addV("TestType").property("name", "1").
......2> addV("TestType").property("name", "2").
......3> V().has("name", "1").as("from").
......4> V().has("name", "2").as("to").
......5> coalesce(inE("DEPENDS_ON").where(outV().as("from")),
......6> addE("DEPENDS_ON").from("from").as('e').
......7> select('props').
......8> unfold().as('kv').
......9> select('e').
.....10> property(select("kv").by(keys), select("kv").by(values))).dedup()
==>e[4][0-DEPENDS_ON->2]
gremlin> g.withSideEffect('props', ["p1": "v1", "p2": "v2"]).
......1> addV("TestType").property("name", "1").
......2> addV("TestType").property("name", "2").
......3> V().has("name", "1").as("from").
......4> V().has("name", "2").as("to").
......5> coalesce(inE("DEPENDS_ON").where(outV().as("from")),
......6> addE("DEPENDS_ON").from("from").as('e').
......7> select('props').
......8> unfold().as('kv').
......9> select('e').
.....10> property(select("kv").by(keys), select("kv").by(values))).dedup()
==>e[4][0-DEPENDS_ON->2]
Я не уверен, что является более интуитивным. Я предпочитаю inject()
, когда мне нужно что-то, чтобы начать обход, но у вас есть addV()
, чтобы поместить объекты в начало, поэтому inject()
кажется там неуклюжим, особенно потому, что addV()
просто заменяет Map
его значение. В этом случае я думаю, что использование withSideEffect()
более явно говорит кому-то, читающему это, каково намерение.