【问题标题】:Gremlin-Python: Returning a fully populated subgraphGremlin-Python:返回一个完全填充的子图
【发布时间】:2019-01-04 20:49:18
【问题描述】:

我正在使用 Gremlin-Python 客户端通过 janusgraph 后端查询 Gremlin 服务器。

运行以下查询:

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-server 和示例代码以返回完整的 填充子图?

根据斯蒂芬的反馈更新了测试用例

# 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 和标签)是 分离为图森的“参考元素”部分?

【问题讨论】:

    标签: gremlin janusgraph gremlin-server gremlinpython


    【解决方案1】:

    您不能使用 Gremlin Python(或任何其他语言变体)将 subgraph() 步骤的结果完全返回为 Graph。问题是 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 中子图对不同语言变体的工作方式,但目前这些是我们仅有的解决方案。

    【讨论】:

    • 感谢 Stephen 提供的非常有用的指点。 gremlinpython 确实是轻量级的,即使使用基于脚本的方法,也只有必要的元素(id 和标签)被分离为 graphson 的“参考元素”部分?我添加了一些我所看到的示例代码,因为我无法分离所有元素。再次感谢!
    • 嗯 - 我没想到。我想你需要多走一步,自己强制序列化并返回一个字符串值。我已更新我的答案以包含该信息
    • 对不起,如果这是一个愚蠢的问题/评论,但是为什么我认为不太推荐的另一个选项是使用 Python 提交脚本,而不是使用基于字节码的请求。?当几乎没有关于如何与真正的远程数据库而不是本地主机上的东西进行DriverRemoveConnection基于字节码的连接的示例/教程时?
    • 参考文档中 gremlin-python 的整个部分都是关于基于字节码的请求(即通过 DriverRemoteConnection 进行远程遍历)。 tinkerpop.apache.org/docs/current/reference/#gremlin-python 那里只有一个关于“提交脚本”的小节。除了将 URL 从“localhost”更改为 IP 地址或主机名之外,您还需要做什么才能连接到“真正的远程数据库”?对不起,如果我没有真正理解你的意思。
    【解决方案2】:

    上述解决方案对我不起作用.. 在 GremlinPython 中使用 SubgraphStrategy 的更好方法:

    sg = g.withStrategies(SubgraphStrategy())
    

    sg 将是一个 GraphTraversalSource.. check official documentation

    例如,如果我想找到带有顶点标签“人”的子图

    sg = g.withStrategies(SubgraphStrategy(vertices=hasLabel('person')))
    

    【讨论】:

    • 最初的问题是寻找使用 Python 客户端反序列化子图的方法。在您的示例中,sg 将不是图形对象,而是 GraphTraversalSource。例如,您仍然需要执行 sg.V().limit(10) 来获取一些顶点。
    • 感谢您指出。我已经修改了错字。但是我尝试了sg = g.E().subgraph('a').cap('a').next(),它不返回子图,而是返回空{}。我对此感到很困惑..
    • 这是一个使用 Python 的示例。我使用 Python 控制台运行它 >>> g.E().limit(10).subgraph('a').cap('a').toList() [{'@type': 'tinker:graph', ' @value': {'顶点': [v[22], v[45], v[34], v[46], v[26], v[15], v[28], v[29], v[6], v[8], v[30], v[20], v[31], v[43]], 'edges': [e[4639][28-route->8], e [4607][26-route->22],e[4719][30-route->34],e[4671][29-route->20],e[4751][31-route->22] , e[4687][29-route->43], e[4655][28-route->46], e[4623][26-route->45], e[4735][31-route-> 6], e[4703][30-route->15]]}}]
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多