为什么API调用在Gremlin Python中不起作用?

时间:2019-09-24 16:32:56

标签: tinkerpop3 gremlin-server gremlinpython

在gremlin-python中,我可以这样做:

for e in g.E().toList():
        print(e)

并得到类似

的结果
e[11][4-created->3]
e[12][6-created->3]
e[7][1-knows->2]
e[8][1-knows->4]
e[9][1-created->3]
e[10][4-created->5]

根据

http://tinkerpop.apache.org/javadocs/3.4.3/core/org/apache/tinkerpop/gremlin/structure/Edge.html

Edge具有inVertex()访问器。 将这个想法翻译成python会导致:

for e in g.E().toList():
        print (e.inVertex().id)

和错误

AttributeError: 'Edge' object has no attribute 'inVertex'

其他许多“简单” API调用也是如此。

for e in g.E().toList():
        print(e.property('weight'))

也失败了

这是什么,什么解决方法?

3 个答案:

答案 0 :(得分:2)

在TinkerPop中,图元素(例如,顶点,边,顶点属性)通常会经历“分离”过程。从远程源返回图形元素的Gremlin遍历将经历此过程,在这种情况下,通常将其分离为“引用”。引用仅提供足够的信息来重新附加到远程图形。对于重新连接的过程,只需要idlabel。因此,不返回属性。 Gremlin支持的所有语言都是相同的,而不仅仅是Python(尽管,在最后的注释中,我会稍稍反对这一说法)。

专门针对Gremlin语言变体(例如Python)说,这些Gremlin的实现没有完整的Gremlin虚拟机来处理遍历,并且从来都不打算在Python端构建完整的图结构-仅包含引用了图的元素匹配从远程源返回的内容。这也减少了需要维护的Python方面的代码量,因为TinkerPop可以依赖所有编程语言中都存在的标准原语,例如DictionaryList等。

除了技术史,参考文献的归还还可以根据最佳实践来编写更好的Gremlin。用户应在Gremlin遍历中准确指定所需的数据。而不是:

g.V().hasLabel('customer')

您希望:

g.V().hasLabel('customer').valueMap(true,'name')

或3.4.4中的

 g.V().hasLabel('customer').elementMap('name')

返回的嵌套结构比valueMap()少。 elementMap()非常适合边缘,并且可以通过project()替代更复杂的方法,以从问题的边缘获取您所请求的数据:

gremlin> g.V().has('person','name','marko').elementMap()
==>[id:1,label:person,name:marko,age:29]
gremlin> g.V().has('person','name','marko').elementMap('name')
==>[id:1,label:person,name:marko]
gremlin> g.V().has('person','name','marko').properties('name').elementMap()
==>[id:0,key:name,value:marko]
gremlin> g.E(11).elementMap()
==>[id:11,label:created,IN:[id:3,label:software],OUT:[id:4,label:person],weight:0.4]

在SQL中,您可能不会这样做并没有什么不同:

SELECT * FROM customer

但相反:

SELECT name FROM customer

返回引用并强制用户对其返回的内容进行更明确的说明也解决了具有多/元属性的巨大问题。如果用户返回顶点而无意中返回了“胖”顶点(例如,具有1百万个属性的顶点),则对尝试返回该顶点的服务器将产生重大影响。通过脱离参考,用户不会陷入任何漏洞。

所有这些,从3.4.3版本开始,仍然存在与分离不一致的问题,并且在Java中,在某些情况下,分离还有其他方法可以用于参考分离之外。 TinkerPop一直试图在这种方法中变得完全一致,但是一直试图以一种不会破坏现有发行版中的现有代码的方式来做到这一点。这可能不是您要寻找的答案,但至少可以帮助您解释事物为什么如此的一些原因和历史。

答案 1 :(得分:0)

查看位于https://github.com/apache/tinkerpop/blob/master/gremlin-python/src/main/jython/gremlin_python/structure/graph.py的源代码(见下文),可以直接访问以下属性:

对于所有元素:

e.id
e.label

对于边缘:

e.inV
e.outV

坏消息是,首先需要检索属性,因此在单个python语句中访问id,标签和属性并不是那么容易。

class Element(object):
    def __init__(self, id, label):
        self.id = id
        self.label = label

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self.id == other.id

    def __hash__(self):
        return hash(self.id)


class Vertex(Element):
    def __init__(self, id, label="vertex"):
        Element.__init__(self, id, label)

    def __repr__(self):
        return "v[" + str(self.id) + "]"


class Edge(Element):
    def __init__(self, id, outV, label, inV):
        Element.__init__(self, id, label)
        self.outV = outV
        self.inV = inV

    def __repr__(self):
        return "e[" + str(self.id) + "][" + str(self.outV.id) + "-" + self.label + "->" + str(self.inV.id) + "]"

答案 2 :(得分:0)

toList()执行gremlin查询并将结果打包在列表中。 因此,您无法使用inVertex()继续遍历。

要获取输入顶点,应运行:

for v in g.E().inV().toList():
        print(v)

要在单个查询中获取边属性和两个顶点属性,可以使用project

g.E().project("values", "in", "out")
    .by(valueMap(true))
    .by(inV().valueMap(true))
    .by(outV().valueMap(true))