如何从顶点获取排他子图? [英] How can I get an exclusive subgraph from a vertex?

查看:161
本文介绍了如何从顶点获取排他子图?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近不得不从使用Cypher更改为Gremlin,并且我试图转换一个查询,该查询允许用户删除"一个节点以及所有受此影响的子图节点.它实际上并没有删除节点,只是在受影响的节点上添加了"DELETED"标签.

I've recently had to change from using Cypher to Gremlin and I'm trying to convert a query that allowed a user to 'delete' a node and all of the subgraph nodes that would be affected by this. It wasn't actually removing nodes but just adding a 'DELETED' label to the affected nodes.

我可以使用以下方法在Gremlin中获得一个子图:

I can get a subgraph in Gremlin using:

g.V(nodeId).repeat(__.inE('memberOf').subgraph('subGraph').outV()).cap('subGraph')

但是,这并未考虑子图中的任何节点,这些节点可能具有回溯到原始已删除"节点之后的路线,因此不应孤立.

but this doesn't take into account any nodes in the subgraph that might have a route back past the originally 'deleted' node and therefore shouldn't be orphaned.

如果采用上述图表; B是要删除的节点.它的子图将包括D,E,G和H.但是,由于E仍然有一条通过C返回A的路线,因此我们不想删除"它. D,G和H将没有返回A的路线,因此也应删除.

If you take the graph above; B is the node being deleted. It's subgraph would include D, E, G and H. However, since E still has a route back to A through C, we don't want to 'delete' it. D, G and H will be left without a route back to A and should therefore also be deleted.

我的Cypher查询的工作方式如下(在C#中使用Neo4jClient.Cypher):

My Cypher query worked like this (using Neo4jClient.Cypher in C#):

// Find the node to be deleted i.e. B
.Match("(b {Id: 'B'})")  
// Set a DELETED label to B   
.Set("b:DELETED")     
.With("b")
// Find the central node i.e A
.Match("(a {Id: 'A'})") 
// Find the subgraph of B ignoring previously deleted nodes
.Call("apoc.path.subgraphAll(b, { relationshipFilter: '<memberOf', labelFilter: '-DELETED'})")     
.Yield("nodes AS subgraph1")
// Get each node in subgraph1 as sg1n
.Unwind("subgraph1", "sg1n") 
// Check if each sg1n node has a route back to A ignoring DELETED routes    
.Call("apoc.path.expandConfig(sg1n, { optional: true, relationshipFilter: 'memberOf>', labelFilter: '-DELETED', blacklistNodes:[b],terminatorNodes:[a]})")     
.Yield("path")
// If there is a path then store the nodes as n
.Unwind("CASE WHEN path IS NULL THEN [null] ELSE nodes(path) END", "n")     
// Remove the nodes in n from the original subgraph (This should leave the nodes without a route back)
.With("apoc.coll.subtract(subgraph1, collect(n)) AS subgraph2") 
// Set the DELETED label on the remaining nodes     
.ForEach("(n IN(subgraph2) | SET n:DELETED)")  

有什么办法可以让我在Gremlin中获得类似的功能吗?

Is there any way I can get similar functionality in Gremlin?

在这个问题和

Thanks to sel-fish's help in this question and in this one, I now have this working using:

g.V(itemId)                                            // Find the item to delete.
  .union(                                              // Start a union to return
    g.V(itemId),                                       // both the item 
    g.V(itemId)                                        // and its descendants.
      .repeat(__.inE('memberOf').outV().store('x'))    // Find all of its descendants.
      .cap('x').unfold()                               // Unfold them.
      .where(repeat(out('memberOf')                    // Check each descendant
        .where(hasId(neq(itemId))).simplePath())       // to see if it has a path back that doesn't go through the original vertex
        .until(hasId(centralId)))                      // that ends at the central vertex .
      .aggregate('exception')                          // Aggregate these together.
      .cap('x').unfold()                               // Get all the descendants again.
      .where(without('exception')))                    // Remove the exceptions.
  .property('deleted', true)                           // Set the deleted property.
  .valueMap(true)                                      // Return the results.

推荐答案

首先,将子图中的顶点另存为candidates:

First, save the vertices in subgraph as candidates:

candidates = g.V().has('Id', 'B').repeat(__.inE('memberOf').subgraph('subGraph').outV()).cap('subGraph').next().traversal().V().toList()

然后,过滤candidates,保留那些未未获得指向Ve​​rtex('A')且不包括Vertex('B')的路径的:

Then, filter the candidates, remains those which doesn't get a path towards Vertex('A') which not including Vertex('B'):

g.V(candidates).where(repeat(out('memberOf').where(has('Id', neq('B'))).simplePath()).until(has('Id','A'))).has('Id', neq('B')).aggregate('expection').V(candidates).where(without('expection'))

这篇关于如何从顶点获取排他子图?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆