CosmosDB Graph:“upsert”查询模式
Posted
技术标签:
【中文标题】CosmosDB Graph:“upsert”查询模式【英文标题】:CosmosDB Graph : "upsert" query pattern 【发布时间】:2018-09-20 08:32:15 【问题描述】:我是 Gremlin 查询语言的新手。 我必须在 Cosmos DB 图上插入数据(使用 Gremlin.Net 包),无论图中是否已经存在顶点(或边缘)。如果数据存在,我只需要更新属性。 我想使用这种模式:
g.V().hasLabel('event').has('id','1').tryNext().orElseGet g.addV('event').has('id','1')
但 Gremlin.Net / Cosmos DB 图形 API 不支持它。有没有办法在单个查询中进行一种 upsert 查询?
提前致谢。
【问题讨论】:
【参考方案1】:有很多方法可以做到这一点,但我认为 TinkerPop 社区普遍采用这种方法:
g.V().has('event','id','1').
fold().
coalesce(unfold(),
addV('event').property('id','1'))
基本上,它使用has()
查找“事件”并使用fold()
步骤强制到一个列表。该列表要么为空,要么包含Vertex
。然后使用coalesce()
,它会尝试unfold()
列表,如果它有一个Vertex
,否则会立即返回,它会执行addV()
。
如果想法是在找到元素后更新现有属性,只需在coalesce()
之后添加property()
步骤:
g.V().has('event','id','1').
fold().
coalesce(unfold(),
addV('event').property('id','1')).
property('description','This is an event')
如果您需要知道返回的顶点是否是“新的”,那么您可以执行以下操作:
g.V().has('event','id','1').
fold().
coalesce(unfold().
project('vertex','exists').
by(identity()).
by(constant(true)),
addV('event').property('id','1').
project('vertex','exists').
by(identity()).
by(constant(false)))
关于这个主题的更多阅读可以在这个问题上找到:“Why do you need to fold/unfold using coalesce for a conditional insert?”
另请注意,此处描述了可选的边缘插入:“Add edge if not exist using gremlin”。
最后一点,虽然这个问题是关于 CosmosDB 的,但答案通常适用于所有启用 TinkerPop 的图。当然,图如何优化这个 Gremlin 是一个单独的问题。如果图具有原生 upsert 功能,则该功能可能会或可能不会在此 Gremlin 的幕后使用,因此可能有更好的方法通过图系统原生 API 实现 upsert(当然,选择该路径会降低你的代码)。
【讨论】:
如果我希望查询也告诉我节点是已经存在还是刚刚创建,该怎么办?到目前为止我想出的是:g.V('1234').fold().as('existing').coalesce(unfold(), addV().property(id,'1234')).as('result').select('existing','result')
,它工作得很好,返回 'existing': [], result: ...
创建节点时,但如果节点已经存在,则复制返回的有效负载: 'existing': [ /*node payload*/ ], result: /*same node payload again*/
我想我找到了更好的方法(刚刚了解了store()
):g.V('1235').fold().store('existing').coalesce(unfold(), addV().property(id,'1235').store('new')).cap('existing','new')
。这样,“现有”或“新”始终为空。让我知道是否有更好的方法来公开负载的布尔标志和单个属性。
你的方法很好,但如果可以的话,避免副作用也很好。用无副作用的遍历和一个简单的布尔值更新了我的答案,作为是否添加顶点的返回值。
太好了!谢谢你的分享。如何避免副作用?这是由于对函数式编程的纯粹性的哲学追求,还是它有可测量的、嗯、副作用?
从左到右阅读 Gremlin 很好,而不必回溯到遍历中的某个较早点,因此从可读性的角度来看,我倾向于认为副作用使 Gremlin 更难理解。由于需要副作用构造,您还会在遍历时产生额外的处理和内存成本,这可能是尝试避免它们的更多原因。以上是关于CosmosDB Graph:“upsert”查询模式的主要内容,如果未能解决你的问题,请参考以下文章
Azure CosmosDB (16) 通过REST API对CosmosDB进行跨分区查询