首页 > 解决方案 > 在 Gremlin 中,仅当版本属性与数字匹配时,如何修改顶点的属性?

问题描述

在 Gremlin/Tinkerpop 中,我想在 Vertex 上执行版本化 upsert。如果有一个现有的顶点,我只想在版本与版本号属性匹配时对其进行变异。

下面是尝试使用gremlinjs. 它无法创建顶点,以后的查询无法找到它。

(以前的版本有一个编译错误,但这是一个 javscriptism 未记录的语法问题)

[更新] 请参阅有关问题的答案的评论。https://gist.github.com/pszabop/3b07fa7caadf1dbd86953a713ed96ce0的工作版本

//
// o.id o.__version, and o.__lastUpdate have special meaning or are reserved
//
graphdb.upsertVertexVersioned = async function(type, o) {
  const g = traversal().withRemote(this.connection);
  let oldVersion;

  if (!o.id) {
    o.id = uuidv4();
  }  
  if (!o.__version) {
    o.__version = 0;
    oldVersion = 0;
  } else {
    oldVersion = o.__version;
    o.__version++;
  }  
  o.__lastUpdate = Date.now();

  // @see http://tinkerpop.apache.org/docs/current/recipes/#element-existence
  // The pattern we are using is keys get copied into properties that can be used
  // by the graph database for its work, and then the
  // entire object is JSON serialized into a generic `obj` property.
  // XXX TBD use graphson?
  const v1 = await g.V().has(type, 'id', o.id) 
  .fold()  
  .coalesce(__.unfold(),
    __.addV(type).property('id', o.id)                       
    .property('version', o.__version)                        
  ).choose(__.values('version').is(oldVersion),
    __.in_() 
    .property('lastUpdate', o.__lastUpdate)                  // updated properties go here
    .property('version', o.__version)                        // updated properties go here
    .property('obj', JSON.stringify(o)),                     // updated properties go here
    __.out()
  ).next();

  return o;
};

参考:

版本

标签: gremlintinkerpopjanusgraphgremlinjs

解决方案


我使用“现代”玩具图尝试了您的代码的变体,事实证明您的代码对我来说是正确的。我相信以下内容抓住了您所做工作的精神:

gremlin> g = TinkerFactory.createModern().traversal()
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g.V().property('version',1).iterate()
gremlin> name = 'marko'
==>marko
gremlin> oldVersion = 1
==>1
gremlin> version = 2
==>2
gremlin> g.V().has('person','name',name).
......1>   fold().
......2>   coalesce(unfold(), 
......3>            addV('person').property('name',name).property('version',version)).
......4>   choose(values('version').is(oldVersion),
......5>          property('version', version).constant('edited'),
......6>          constant('same'))
==>edited
gremlin> g.V().has('person','name',name).
......1>   fold().
......2>   coalesce(unfold(), 
......3>            addV('person').property('name',name).property('version',version)).
......4>   choose(values('version').is(oldVersion),
......5>          property('version', version).constant('edited'),
......6>          constant('same'))
==>same
gremlin> name = 'stephen'
==>stephen
gremlin> g.V().has('person','name',name).
......1>   fold().
......2>   coalesce(unfold(), 
......3>            addV('person').property('name',name).property('version',version)).
......4>   choose(values('version').is(oldVersion),
......5>          property('version', version).constant('edited'),
......6>          constant('same'))
==>same
gremlin> g.V().has('person','name',name).
......1>   fold().
......2>   coalesce(unfold(), 
......3>            addV('person').property('name',name).property('version',version)).
......4>   choose(values('version').is(oldVersion),
......5>          property('version', version).constant('edited'),
......6>          constant('same'))
==>same
gremlin> oldVersion = 2
==>2
gremlin> version = 3
==>3
gremlin> 
gremlin> g.V().has('person','name',name).
......1>   fold().
......2>   coalesce(unfold(), 
......3>            addV('person').property('name',name).property('version',version)).
......4>   choose(values('version').is(oldVersion),
......5>          property('version', version).constant('edited'),
......6>          constant('same'))
==>edited
gremlin> g.V().has('person','name',name).
......1>   fold().
......2>   coalesce(unfold(), 
......3>            addV('person').property('name',name).property('version',version)).
......4>   choose(values('version').is(oldVersion),
......5>          property('version', version).constant('edited'),
......6>          constant('same'))
==>same
gremlin> g.V().has('person','name','stephen').elementMap()
==>[id:19,label:person,name:stephen,version:3]

鉴于您对问题的描述,我建议您尝试简化一下。你说的问题是:

它无法创建顶点,以后的查询无法找到它。

choose()如果您删除逻辑,它是否可以正常工作?换句话说,你能让基本的 upsert 操作工作吗?如果不是,那么问题似乎与查询的那部分无关,尽管您所拥有的似乎遵循推荐的做法,所以我不确定可能有什么问题。


推荐阅读