【问题标题】:Update a vertex and a all its child vertexes and edges更新一个顶点及其所有子顶点和边
【发布时间】:2021-01-23 15:15:44
【问题描述】:

我有像这样的 JSON 实体,我将它们作为边和顶点插入到图中,如您所见,每个实体都已经是高度相关的格式。

person = {
    "summary": "Unix System Administrator at National Bank of Canada",
    "id": "P6ZiIHhJ-PhON9W6UgeFwfA",
    "name": "Patrick",
    "type": "Person",
    "employments": [
        {
            "isCurrent": True,
            "employer": {
                "Name": "Commercial bank located in Canada",
                "type": "Corporation"
            },
            "title": "Unix System Administrator"
        }
    ],
    "skills": [
        {
            "name": "string"
        }
    ],
    "locations": [
        {
            "country": {
                "name": "Canada",
                "type": "AdministrativeArea"
            }
        }
    ],
    "someVertex": {
        "k": "v"
    }
}

结果图:


我的问题是,将来,我可能会收到同一个人的新 json,如果发生变化,我需要在图中“更新”它,并确保删除任何不再存在的子顶点。有点像 upsert,但在所有子节点和边上。

现在,我将根 id 作为属性添加到每个子元素上,这样我就可以找到它们并在以后删除它们。有没有其他方法可以做到这一点?

我的实际过程:

  1. 递归地从python dict中添加所有verticles和edges,嵌套的dicts都成为顶点,并在它和父级之间添加一条边。
def add_vertex(g, label, dct, entity_id):
   vertex = g.addV(label).property('entity_id', entity_id)
   add_properties(g, vertex, dct, entity_id)
   return vertex


def add_properties(g, vertex, dct, entity_id):
   # Add properties
   for k, v in dct.items():
       if type(v) in [str, bool, int, float]:
           vertex = vertex.property(k, v)

       elif v and isinstance(v, list) and type(v[0]) in [str, bool, int, float]:
           for literal in v:
               vertex = vertex.property(Cardinality.set_, k, literal)

   vertex = vertex.next()

   # Add child vertexes and edges to them
   for k, v in dct.items():
       if isinstance(v, dict):
           nested_vertex = add_vertex(g, k, v, entity_id)
           add_edge(g, k, vertex, nested_vertex, entity_id)

       elif v and isinstance(v, list) and isinstance(v[0], dict):
           for nested_v in v:
               nested_vertex = add_vertex(g, k, nested_v, entity_id)
               add_edge(g, k, vertex, nested_vertex, entity_id)


def add_edge(g, name, from_v, to_v, entity_id):
   g.addE(name).property('entity_id', entity_id).from_(from_v).to(to_v).iterate()


add_vertex(g, 'Person', person , person['id'])
  1. 如果我收到具有相同 id 的人,想象顶点“someVertex”现在不在字典中,我如何“插入”最初来自此人的整个顶点和边树,以便该顶点已移除?现在,我删除了我在上一步中添加的具有“entity_id”属性的所有元素。
if g.V().has(entity_type, 'id', entity_id).hasNext():
    g.V().has('entity_id', entity_id).drop().iterate()
    add_vertex(g, entity_type, entity, entity_id)

【问题讨论】:

  • 您是说您的 upserting 方法会留下需要稍后删除的孤立子顶点吗?是否有某些原因您不能在执行 upsert 时删除孩子?或许你可以多描述/展示一下这个过程?
  • @stephenmallette 我添加了一些信息,我是新的小精灵和图表,也许我的第一步也有一些需要改进的地方,因为它很慢。谢谢。

标签: python graph gremlin tinkerpop3 amazon-neptune


【解决方案1】:

向所有顶点添加“entity_id”属性并不是找到所有要删除的顶点的可怕方法。一种更面向图的方法是简单地跟随父节点的边递归地删除您找到的所有顶点:

gremlin> g = TinkerGraph.open().traversal()
==>graphtraversalsource[tinkergraph[vertices:0 edges:0], standard]
gremlin> g.addV().property(id, 'A').as('a').
......1>   addV().property(id, 'B').as('b').
......2>   addV().property(id, 'C').as('c').
......3>   addV().property(id, 'E').as('e').
......4>   addV().property(id, 'F').as('f').
......5>   addE('hasParent').from('a').to('b').
......6>   addE('hasParent').from('b').to('c').
......7>   addE('hasParent').from('c').to('e').
......8>   addE('hasParent').from('e').to('f').iterate()
gremlin> g.V().has(id,'B').
......1>   emit().
......2>   repeat(out()).
......3>   aggregate('x').
......4>   select('x').unfold().
......5>   drop()
gremlin> g.V().elementMap()
==>[id:A,label:vertex]

我首先选择aggregate() 他们,因为大多数图表更喜欢我认为的那种方法(而不是在你遍历时丢弃),但你也可以尝试这样做以避免收集“x”的副作用List ”。

有一些方法可以使用更真实的 upsert 样式语义来更新图形结构。虽然你有一个相当健壮的树结构,所以我觉得这将构成一个相当厚实和复杂的 Gremlin。在您的情况下,将其全部删除并重新添加可能最有意义 - 很难说。在 StackOverflowother places 上的许多地方都描述了这种 upsert 模式,您可能会四处搜索。

【讨论】:

    猜你喜欢
    • 2021-12-27
    • 1970-01-01
    • 2011-06-30
    • 1970-01-01
    • 1970-01-01
    • 2021-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多