更新顶点及其所有子顶点和边
Update a vertex and a all its child vertexes and edges
我有 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 作为 属性 添加到每个子元素上,这样我就可以找到它们并稍后删除它们。还有其他方法吗?
我的实际过程:
- 递归添加python字典中的所有顶点和边,嵌套字典全部变成顶点,并在它和父字典之间添加一条边。
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'])
- 如果我收到具有相同 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)
向所有顶点添加“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()
它们,因为我认为大多数图表更喜欢这种方法(而不是在遍历时丢弃),但您也可以尝试这样做以避免收集 side-effect List
个“x”。
有一些方法可以使用更真实的更新插入样式语义来更新图结构。虽然你有一种相当健壮的树结构,所以我觉得这将构成一个相当粗壮和复杂的 Gremlin。在您的情况下,将其全部删除并重新添加可能最有意义-很难说。 and other places 上的许多地方都描述了 upserts 的模式,您可以四处搜索。
我有 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 作为 属性 添加到每个子元素上,这样我就可以找到它们并稍后删除它们。还有其他方法吗?
我的实际过程:
- 递归添加python字典中的所有顶点和边,嵌套字典全部变成顶点,并在它和父字典之间添加一条边。
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'])
- 如果我收到具有相同 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)
向所有顶点添加“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()
它们,因为我认为大多数图表更喜欢这种方法(而不是在遍历时丢弃),但您也可以尝试这样做以避免收集 side-effect List
个“x”。
有一些方法可以使用更真实的更新插入样式语义来更新图结构。虽然你有一种相当健壮的树结构,所以我觉得这将构成一个相当粗壮和复杂的 Gremlin。在您的情况下,将其全部删除并重新添加可能最有意义-很难说。