Gremlin-Python: возвращение полностью заполненного подграфа
Я использую Gremlin-Python Client для запросов к Gremlin Server с бэкэндом janusgraph.
Выполнение следующего запроса:
graph = Graph()
g = graph.traversal().withRemote(DriverRemoteConnection('ws://localhost:8182/gremlin','g'))
sg = g.E().subgraph('a').cap('a').next()
Запрос возвращает подграф, содержащий список ребер и вершин.
У меня на сервере настроены следующие сериализаторы
serializers:
- { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry] }}
- { className: org.apache.tinkerpop.gremlin.driver.ser.GryoMessageSerializerV3d0, config: { serializeResultToString: true }}
- { className: org.apache.tinkerpop.gremlin.driver.ser.GraphSONMessageSerializerV3d0, config: { ioRegistries: [org.janusgraph.graphdb.tinkerpop.JanusGraphIoRegistry] }}
Кто-нибудь знает, как настроить gremlin-сервер и пример кода для возврата полностью заполненного подграфа?
Обновлен контрольный пример, основанный на отзывах Стивена
# DB: Janusgraph with Opensource Cassandra storage backend
# Data: v[41427160]--reports_to-->v[36712472]--reports_to-->v[147841048]
# Objective: get subgraph detached to python client with all properties of the vertex and edges
(py365)$ pip list | grep gremlinpython
gremlinpython 3.3.4
(py365)$ python
Python 3.6.5 (default, Apr 25 2018, 14:26:36)
[GCC 4.2.1 Compatible Apple LLVM 9.0.0 (clang-900.0.39.2)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from gremlin_python.driver import client
>>> from gremlin_python.driver.serializer import GraphSONSerializersV3d0
>>> session = client.Client('ws://localhost:8182/gremlin', 'g', message_serializer=GraphSONSerializersV3d0())
>>> query_parameters = {"vids": [41427160, 36712472]}
>>> query = "g.V(vids).outE('reports_to').subgraph('1').otherV().cap('1').next()"
>>> results = session.submit(query, query_parameters)
>>> for r in results:
... r_vertices = r[0]['@value'].get('vertices')
... r_edges = r[0]['@value'].get('edges')
... print(r)
... print(r_vertices)
... print(r_edges)
...
[{'@type': 'tinker:graph', '@value': {'vertices': [v[41427160], v[147841048], v[36712472]], 'edges': [e[{'@type': 'janusgraph:RelationIdentifier', '@value': {'relationId': '21y8ez-onxeg-f11-luviw'}}][41427160-reports_to->36712472], e[{'@type': 'janusgraph:RelationIdentifier', '@value': {'relationId': '225dz7-luviw-f11-2g0qvs'}}][36712472-reports_to->147841048]]}}]
[v[41427160], v[147841048], v[36712472]]
[e[{'@type': 'janusgraph:RelationIdentifier', '@value': {'relationId': '21y8ez-onxeg-f11-luviw'}}][41427160-reports_to->36712472], e[{'@type': 'janusgraph:RelationIdentifier', '@value': {'relationId': '225dz7-luviw-f11-2g0qvs'}}][36712472-reports_to->147841048]]
>>>
Правда ли, что gremlinpython является легковесным, что даже при использовании подхода, основанного на сценариях, только необходимые элементы (id и label) отсоединяются в качестве "ссылочных элементов" части Graphson?
1 ответ
Вы не можете полностью вернуть результат subgraph()
шаг как Graph
с Gremlin Python (или любым другим языковым вариантом в этом отношении). Проблема заключается в том, что Gremlin Python предназначен для облегченной реализации Gremlin и поэтому не имеет экземпляра структуры данных графа для десериализации возвращаемых данных.
В настоящее время единственный обходной путь - просто вернуть данные, которые формируют график, и тогда вам нужно будет сохранить эти данные во что-то похожее на граф в Python. Так что, возможно, вы бы сделали:
g.E().project('edgeId','label','inId','outId').
by(id).
by(label).
by(inV().id()).
by(outV().id())
Это вернуло бы минимальные данные, необходимые для структуры подграфа в виде Map
и тогда вы могли бы что-то сделать с этими данными в Python.
Другим вариантом, который я считаю менее рекомендуемым, будет отправка скрипта с Python, а не использование запроса на основе байт-кода. С помощью скрипта вы получили бы представление GraphSON для подграфа, а затем могли бы при необходимости проанализировать его для некоторой структуры данных в Python. Вот эквивалент сценария, который вам нужно отправить:
gremlin> graph = g.E().hasLabel('knows').subgraph('sg').cap('sg').next()
==>tinkergraph[vertices:3 edges:2]
gremlin> mapper = GraphSONMapper.build().addRegistry(TinkerIoRegistryV3d0.instance())create().createMapper()
==>org.apache.tinkerpop.shaded.jackson.databind.ObjectMapper@f6de586
gremlin> mapper.writeValueAsString(graph)
==>{"@type":"tinker:graph","@value":{"vertices":[{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":1},"label":"person","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":0},"value":"marko","label":"name"}}],"age":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":1},"value":{"@type":"g:Int32","@value":29},"label":"age"}}]}}},{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":2},"label":"person","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":2},"value":"vadas","label":"name"}}],"age":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":3},"value":{"@type":"g:Int32","@value":27},"label":"age"}}]}}},{"@type":"g:Vertex","@value":{"id":{"@type":"g:Int32","@value":4},"label":"person","properties":{"name":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":6},"value":"josh","label":"name"}}],"age":[{"@type":"g:VertexProperty","@value":{"id":{"@type":"g:Int64","@value":7},"value":{"@type":"g:Int32","@value":32},"label":"age"}}]}}}],"edges":[{"@type":"g:Edge","@value":{"id":{"@type":"g:Int32","@value":7},"label":"knows","inVLabel":"person","outVLabel":"person","inV":{"@type":"g:Int32","@value":2},"outV":{"@type":"g:Int32","@value":1},"properties":{"weight":{"@type":"g:Property","@value":{"key":"weight","value":{"@type":"g:Double","@value":0.5}}}}}},{"@type":"g:Edge","@value":{"id":{"@type":"g:Int32","@value":8},"label":"knows","inVLabel":"person","outVLabel":"person","inV":{"@type":"g:Int32","@value":4},"outV":{"@type":"g:Int32","@value":1},"properties":{"weight":{"@type":"g:Property","@value":{"key":"weight","value":{"@type":"g:Double","@value":1.0}}}}}}]}}
В следующих версиях TinkerPop мы пересмотрим, как работает подграфия для разных языковых вариантов, но пока это единственные решения, которые у нас есть.
Вышеупомянутое решение не работает для меня.. Лучший способ сделать это с помощью SubgraphStrategy в GremlinPython:
sg = g.withStrategies(SubgraphStrategy())
sg будет GraphTraversalSource.. проверьте официальную документацию
например, если я хочу найти подграф с меткой вершины "человек"
sg = g.withStrategies(SubgraphStrategy(vertices=hasLabel('person')))