Gremlin - 仅在顶点不存在时添加顶点

14

我有一个用户名数组(例如['abc','def','ghi']),需要将它们添加到图表的“user”标签下。

现在,我首先要检查用户名是否已经存在(g.V().hasLabel('user').has('username','def')),然后只添加那些用户名属性不匹配的用户到“user”标签下。

另外,这可以通过单个Gremlin查询或Groovy脚本完成吗?

我正在使用Titan图形数据库、TinkerPop3和Gremlin REST服务器。


我在这里回答了一个类似的问题: https://dev59.com/5q3la4cB1Zd3GeqPNHfw#76353284。那里描述的方法允许在单个请求中添加多个对象,并且不需要使用 fold()/unfold() - Gyromite
3个回答

42

使用“脚本”,您可以始终将多行/命令脚本传递到服务器进行处理,以完成您想要的操作。然后,可以使用常规编程技术(如变量、if / then语句等)来回答这个问题:

t = g.V().has('person','name','bill')
t.hasNext() ? t.next() : g.addV('person').property('name','bill').next()

或者说:

g.V().has('person','name','bill').tryNext().orElseGet{
    g.addV('person').property('name','bill').next()}

但是这些都是Groovy脚本,TinkerPop最终建议避免使用脚本和闭包,而是使用纯遍历。处理单个遍历中的“获取或创建”的一般方法是执行以下操作:

gremlin> g.V().has('person','name','bill').fold().
......1>   coalesce(unfold(), 
......2>            addV('person').property('name','bill'))
==>v[18]

另请参阅此 StackOverflow问题,了解有关upsert /“获取或创建”模式的更多信息。

更新:从TinkerPop 3.6.0开始,fold()/ coalesce()/ unfold()模式已经在很大程度上被新步骤所取代 mergeV()mergeE()。这极大地简化了执行类似upsert操作所需的Gremlin。在3.6.0及更高版本下,您应编写以下内容:

g.mergeV([(label): 'person', name: 'bill'])

我正在从我的Nodejs服务器向Gremlin发起REST调用。因此,如果我需要添加200个用户,那么我是否应该调用以上命令200次?如果其中几个出现异常或错误,该如何处理并且应该回滚吗?请让我知道这种情况下的正确方法。 - Vipul Sharma
如果您致力于REST并使用脚本,则只需将我的最后一条语句转换为处理200个用户批次的脚本。其中,users是一个参数,包含200个用户的列表。使用REST和批处理方法,要么整个批次成功,要么全部失败。如果您想要其他操作,请修改脚本以在循环中包含try/catch以采用不同的方式进行处理。使用脚本,您基本上可以使用Groovy来完成所需的任何操作。 - stephen mallette

1
你可以直接使用:

来完成。

g.V().has('user','username','def').fold().coalesce(unfold(),addV('user').property('username','def'))

0

在这个答案中补充一点。最好使用以下幂等查询。Coalesce的工作原理类似于if-else语句。有关更多信息,请参见https://spin.atomicobject.com/2021/08/10/idempotent-queries-in-gremlin/。此外,如果您注意到条目未被保存,请确保使用.next()提交更改。

g.V().hasLabel('user').has('username','def')
    .fold()
    .coalesce(
        __.unfold(), 
        __.addV('user').property('username','def')
    )
    .next()

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