如何使用Gremlin Python在Gremlin服务器上提交更改

9
我正在撰写一份脚本,使用gremlin-python库在gremlin-server上创建一个图表。我找不到关于该库的任何好的文档。
以下是我正在尝试的代码结构:
from    gremlin_python                                  import statics
from    gremlin_python.structure.graph                  import Graph
from    gremlin_python.process.graph_traversal          import __
from    gremlin_python.process.strategies               import *
from    gremlin_python.driver.driver_remote_connection  import DriverRemoteConnection

graph = Graph()

g = graph.traversal().withRemote(DriverRemoteConnection('ws://localhost:8182/gremlin','try1'))

# Drop all vertices in the graph to create a new one
g.V().drop().iterate()

a = g.addV('person').property('name', 'Tushar').property('pronoun', 'me')
b = g.addV('person').property('name', 'Avi').property('pronoun','you')

e1 = a.addE('knows').to(b).property('relation','self')

c = g.addV('subject').property('name','maths')

e2 = a.addE('studies').to(c)

e3 = b.addE('studies').to(c)
e3.next()

v = g.V().toList()
e = g.E().toList()

print(v)
print(e)

这段代码只给我2个顶点和1条边。
我的一些尝试:
- 当我尝试不使用.next()的代码时,没有数据提交到图形中。 - 当我给e1一个.next()时,创建了2个不同的顶点和1个不同的边。 - 当我在e2e1上添加.next()时,会抛出一个错误,说StopIteration。 - 当我在e3e1上添加.next()时,我得到了4个顶点和2条边。 我的图应该有3个顶点和3个节点。我真正想要的是将脚本所做的更改提交到图形中。
一些额外的信息:
- 我正在以graphson格式存储图形。 - 我正在使用Python3.6。
1个回答

18

您需要迭代遍历。换句话说,当您进行这种赋值操作时:

a = g.addV('person').property('name', 'Tushar').property('pronoun', 'me') 

没有任何内容被发送到服务器,"a"不包含你的新顶点。你只是将一个Traversal实例赋值给了"a"——请参见以下Groovy示例:

gremlin> t = g.addV('person').property('name','tushar').property('pronoun','me');[]
gremlin> t.class
==>class org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.DefaultGraphTraversal
gremlin> a = t.next()
==>v[0]
gremlin> a.class
==>class org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerVertex

因此,这导致了下一个问题。你可能认为"a"是一个Vertex对象,并想在其上调用addE()方法,但我们已经确定"a"实际上是一个Traversal。首先,Vertex没有addE()方法,因此即使"a"是Vertex对象,这种方法也不起作用。其次,由于你有一个具有addE()方法的Traversal对象,所以你最终会遇到Groovy中展示的这种情况:
gremlin> a = g.addV('person').property('name', 'Tushar').property('pronoun', 'me');[]
gremlin> b = g.addV('person').property('name', 'Avi').property('pronoun','you');[]
gremlin> 
gremlin> e1 = a.addE('knows').to(b).property('relation','self');[]
gremlin> e1.toString()
==>[AddVertexStartStep({pronoun=[me], label=[person], name=[Tushar]}), AddEdgeStep({label=[knows], ~to=[[AddVertexStartStep({pronoun=[you], label=[person], name=[Avi]})]], relation=[self]})]
gremlin> 
gremlin> c = g.addV('subject').property('name','maths');[]
gremlin> 
gremlin> e2 = a.addE('studies').to(c);[]
gremlin> e2.toString()
==>[AddVertexStartStep({pronoun=[me], label=[person], name=[Tushar]}), AddEdgeStep({label=[knows], ~to=[[AddVertexStartStep({pronoun=[you], label=[person], name=[Avi]})]], relation=[self]}), AddEdgeStep({label=[studies], ~to=[[AddVertexStartStep({label=[subject], name=[maths]})]]})]
gremlin> 
gremlin> e3 = b.addE('studies').to(c);[]
gremlin> e3.toString()
==>[AddVertexStartStep({pronoun=[you], label=[person], name=[Avi]}), AddEdgeStep({label=[studies], ~to=[[AddVertexStartStep({label=[subject], name=[maths]})]]})]
gremlin> e3.next()
==>e[8][3-studies->6]
gremlin> g.E()
==>e[8][3-studies->6]

请注意我使用了toString()的行。同样,你没有得到你期望的结果,而是得到了一个Traversal。在每个toString()的遍历中,你可以看到你实际上只是构建了一个更复杂的遍历,将一个遍历嵌套在另一个遍历中。更详细地解释第一个遍历:
gremlin> a = g.addV('person').property('name', 'Tushar').property('pronoun', 'me');[]
gremlin> b = g.addV('person').property('name', 'Avi').property('pronoun','you');[]
gremlin> e1 = a.addE('knows').to(b).property('relation','self');[]
gremlin> e1.toString()
==>[AddVertexStartStep({pronoun=[me], label=[person], name=[Tushar]}), AddEdgeStep({label=[knows], ~to=[[AddVertexStartStep({pronoun=[you], label=[person], name=[Avi]})]], relation=[self]})]

因此,通过这些代码行,您基本上构建了遍历:

g.addV('person').property('name', 'Tushar').property('pronoun', 'me').
  addE('knows').to(addV('person').
                   property('name', 'Avi').
                   property('pronoun','you')).property('relation','self')

那么 "e1" 永远不会被迭代,因此数据永远不会被添加。为了使代码正常工作,您应该按照以下方式进行修改:

from    gremlin_python                                  import statics
from    gremlin_python.structure.graph                  import Graph
from    gremlin_python.process.graph_traversal          import __
from    gremlin_python.process.strategies               import *
from    gremlin_python.driver.driver_remote_connection  import DriverRemoteConnection

graph = Graph()

g = graph.traversal().withRemote(DriverRemoteConnection('ws://localhost:8182/gremlin','try1'))

# Drop all vertices in the graph to create a new one
g.V().drop().iterate()

a = g.addV('person').property('name', 'Tushar').property('pronoun', 'me').next()
b = g.addV('person').property('name', 'Avi').property('pronoun','you').next()
g.addE('knows').from_(a).to(b).property('relation','self').iterate()

c = g.addV('subject').property('name','maths').next()

e2 = g.addE('studies').from_(a).to(c).next()

e3 = g.addE('studies').from_(b).to(c).next()

v = g.V().toList()
e = g.E().toList()

print(v)
print(e)

我认为上述语法只能在最新版本的TinkerPop上工作。个人而言,我更喜欢将上述内容简单写为:

gremlin> g.addV('person').property('name', 'Tushar').property('pronoun', 'me').as('a').
......1>   addV('person').property('name', 'Avi').property('pronoun','you').as('b').
......2>   addV('subject').property('name','maths').as('c').
......3>   addE('knows').from_('a').to('b').property('relation','self').
......4>   addE('studies').from_('a').to('c').
......5>   addE('studies').from_('a').to('c').iterate()
gremlin> g.E()
==>e[23][15-knows->18]
==>e[24][15-studies->21]
==>e[25][15-studies->21]

以此方式,您的遍历仅发送一次到服务器,并在单个请求中生成所有数据。
最后,关于:
“我找不到该库的任何好文档。”
您会注意到我在Gremlin控制台中演示了您的代码,它是基于Groovy的,可以直接复制/粘贴。因此,与Gremlin相关的任何文档都将对您有所帮助。请不要被您遇到的大多数示例都是Groovy语言所迷惑。唯一的区别是特定于语言的语法(例如,Java没有用单引号表示字符串,Python有一些步骤与Python中的保留字冲突,因此它们在末尾加了一个下划线,如not_)。基本上,无论您选择使用哪种语言,Gremlin都是Gremlin-只需学习语法上的微小差异,就应该更容易上手。话虽如此,我们希望将更多的文档翻译成特定于语言的语法-如果您有兴趣,请关注GitHub问题

当请求以多个语句/行发送时,它不会回滚。有什么解决办法吗? - Thirumal
1
这要看情况——如果你在谈论 Gremlin Console 并且使用了 :remote,那么你需要使用 "session" 标志:https://tinkerpop.apache.org/docs/current/reference/#console-sessions 如果你在谈论应用程序中的 Gremlin 代码,则需要使用支持事务的图形会话提交脚本——请参阅此处所使用的编程语言的 "Submitting Scripts" 部分:https://tinkerpop.apache.org/docs/current/reference - stephen mallette
1
最终,对于3.5.0版本,Java具有字节码的远程事务 https://tinkerpop.apache.org/docs/3.5.0/upgrade/#_transaction_improvements - 其他编程语言也将在未来的3.5.x版本中支持此模型。 - stephen mallette
谢谢@stephen mallette,我在应用程序中正在寻找Gremlin代码。感谢您的时间,非常感激。 - Thirumal
@stephenmallette 这个回答非常棒。如果可以的话,我会投100个赞。 - tavor999

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接