Combine two graphs

385 views
Skip to first unread message

Fred Eisele

unread,
Jan 22, 2021, 12:24:13 PM1/22/21
to Gremlin-users
I have two graphs which I wish to merge into one.

Approaches:
* use g2.io() to write one graph to a file and they use g1.io() to read the file into the other graph
* I suspect the PartitionStrategy may be of some use?

Why:
I want to clone a subgraph of g1 -> g2, and make some changes to it, g2, without afflicting g1.

The approach that I know works is ugly. I suspect there is a better way?
Message has been deleted

Fred Eisele

unread,
Jan 22, 2021, 3:45:09 PM1/22/21
to Gremlin-users
Apparently, the `g.io(...).read().iterate()` does not respect the strategies on `g`.
The read does not add the elements to writePartition specified.
e.g.
```
gremlin> graph = TinkerGraph.open()

gremlin> basePartition = PartitionStrategy.
   build().
   partitionKey("_partition").
   writePartition("designA").
   create()
gremlin> g = traversal().withEmbedded(graph).withStrategies(basePartition)
gremlin> g.io("/tmp/all.graphml").with(IO.reader,IO.graphml).read().iterate()

gremlin> graph
==>tinkergraph[vertices:5324 edges:7124]
gremlin> g
==>graphtraversalsource[tinkergraph[vertices:5324 edges:7124], standard]
gremlin> g.V().count()
==>0
gremlin> g.addV('foo')
==>v[15932]
gremlin> g.V().count()
==>1
gremlin> g.V().elementMap()
==>[id:15932,label:foo,_partition:designA]
```

Stephen Mallette

unread,
Jan 25, 2021, 6:53:38 AM1/25/21
to gremli...@googlegroups.com
g.io() doesn't write data using Gremlin mutation steps so strategies are ignored. If the graph is small, you could maybe just subgraph() the whole thing:

clone = sg.E().subgraph('x').cap('x').next()

--
You received this message because you are subscribed to the Google Groups "Gremlin-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-user...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/gremlin-users/20dd8f3f-2772-4ffe-b64d-3597978578cdn%40googlegroups.com.

Fred Eisele

unread,
Jan 25, 2021, 11:17:04 AM1/25/21
to Gremlin-users

It seems the `subgraph()...cap()` pattern produces a new graph?
Is there a way to merge that subgraph back into the original graph?
That is what I was doing with the `g.io()...read()` pattern.


Stephen Mallette

unread,
Jan 25, 2021, 12:58:36 PM1/25/21
to gremli...@googlegroups.com
On Mon, Jan 25, 2021 at 11:17 AM Fred Eisele <fredric...@gmail.com> wrote:

It seems the `subgraph()...cap()` pattern produces a new graph?

It doesn't have to. I think the only requirement is that the graph you subgraph() into support user supplied ids. so you could use withSideEffect() and pass in an existing graph instance and subgraph to that. Of course you will not get a merge operation with that. It will simply do addVertex() and if the id already exists I guess the call would fail. 
 
Is there a way to merge that subgraph back into the original graph?

no - nothing easy. i've thought about that a lot of it is not a trivial problem to solve generically unfortunately. i think you are stuck with having to develop your own methods for merging, resolving conflicts, etc.
 
That is what I was doing with the `g.io()...read()` pattern.


--
You received this message because you are subscribed to the Google Groups "Gremlin-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-user...@googlegroups.com.

Fred Eisele

unread,
Jan 27, 2021, 6:08:02 PM1/27/21
to Gremlin-users

It doesn't have to. I think the only requirement is that the graph you subgraph() into support user supplied ids.
So you could use withSideEffect() and pass in an existing graph instance and subgraph to that. 
 
Could you give a short example of what you mean?
Suppose I have a traversal like the following:

sgraph = graph.traversal().V().outE().subgraph('sg').bothE().subgraph('sg').cap('sg').next()

The `sgraph` I get back appears to be disjoint from `graph`.
Are you saying I can somehow use withSideEffect() to add the `sg` edges (and vertices) into `graph`?

Stephen Mallette

unread,
Jan 29, 2021, 2:15:51 PM1/29/21
to gremli...@googlegroups.com
I just meant that you can pass an existing graph to your traversal - it doesn't have to be initialized by the subgraph() step which means that you can subgraph() into an existing graph if you wanted:

gremlin> sg = TinkerGraph.open()
==>tinkergraph[vertices:0 edges:0]
gremlin> g
==>graphtraversalsource[tinkergraph[vertices:6 edges:6], standard]
gremlin> g1 = g.withSideEffect('sg',sg).E().hasLabel('knows').subgraph('sg').cap('sg').next()
==>tinkergraph[vertices:3 edges:2]
gremlin> g1 == sg
==>true
gremlin> g1
==>tinkergraph[vertices:3 edges:2]
gremlin> sg = TinkerFactory.createTheCrew()
==>tinkergraph[vertices:6 edges:14]
gremlin> g1 = g.withSideEffect('sg',sg).E().hasLabel('knows').subgraph('sg').cap('sg').next()
==>tinkergraph[vertices:8 edges:16]
gremlin> g1 == sg
==>true
gremlin> g1.traversal().E()
==>e[7][1-knows->2]
==>e[8][1-knows->4]
==>e[13][1-develops->10]
==>e[14][1-develops->11]
==>e[15][1-uses->10]
==>e[16][1-uses->11]
==>e[17][7-develops->10]
==>e[18][7-develops->11]
==>e[19][7-uses->10]
==>e[20][7-uses->11]
==>e[21][8-develops->10]
==>e[22][8-uses->10]
==>e[23][8-uses->11]
==>e[24][9-uses->10]
==>e[25][9-uses->11]
==>e[26][10-traverses->11]

gremlin> g1.traversal().V().has('person','name','marko')
==>v[1]
gremlin> g1.traversal().V().has('person','name','marko').outE()
==>e[16][1-uses->11]
==>e[15][1-uses->10]
==>e[13][1-develops->10]
==>e[14][1-develops->11]
==>e[7][1-knows->2]
==>e[8][1-knows->4]




--
You received this message because you are subscribed to the Google Groups "Gremlin-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-user...@googlegroups.com.

Fred Eisele

unread,
Jan 29, 2021, 7:09:14 PM1/29/21
to Gremlin-users
Oh, I see, that's cool.

mgraph = TinkerFactory.createModern()
//==>tinkergraph[vertices:6 edges:6]
mg = mgraph.traversal()
mg.V().elementMap()
mg.E().elementMap()

cgraph = TinkerFactory.createTheCrew()
//==>tinkergraph[vertices:6 edges:14]
cg = cgraph.traversal()
cg .V().elementMap()
cg .E().elementMap()

ngraph = mg.withSideEffect('sg',cgraph).E().hasLabel('knows').subgraph('sg').cap('sg').next()
//==>tinkergraph[vertices:8 edges:16]
ng = ngraph.traversal()
ng.V().elementMap()
ng.E().elementMap()

ngraph == mgraph  //==>false
ngraph == cgraph   //==>true

Repeated application of...
ngraph = mg.withSideEffect('sg',cgraph).E().hasLabel('knows').subgraph('sg').cap('sg').next() 
...produces no errors.
So, the question is, does the repeated insertion of the edges (and their nodes) fail quietly or do they overwrite the previous edges (nodes)?
A quick test shows that the vertex is being overwritten.

cg.V(2).property('age','270').property('foo','bar').iterate()
ngraph = mg.withSideEffect('sg',cgraph).E().hasLabel('knows').subgraph('sg').cap('sg').next() 
ng.V().elementMap()
//==>[id:2,label:person,foo:bar,name:vadas,age:270]

This is actually the type of merge behavior I am looking for!
Is this part of the TinkerPop specification? or just a TinkerGraph behavior?
In other words, can I expect other graph engines to behave in the same way? like JanusGraph?



Stephen Mallette

unread,
Feb 1, 2021, 7:14:25 AM2/1/21
to gremli...@googlegroups.com
I suggest you test it with your graph, but generally speaking subgraph() will look for an existing vertex/edge by id. If it finds one then properties will remain unchanged. If it does not find one it will create it and set properties. Have a look at the code here - it is fairly straightforward:



--
You received this message because you are subscribed to the Google Groups "Gremlin-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to gremlin-user...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages