Gremlin query group by clause - gremlin

I am using neptune graph database. Need help writing a query with a group by clause.
We have three nodes
CAMPAIGN → AD → LP
Campaign to Ad is 1 to many mapping
AD to LP is 1 to 1 mapping
Suppose we have the following vertices and associations
C1 → A1 → LP1
C1 → A2 → LP1
C2 → A3 → LP1
C2 → A4 → LP1
C3 → A5 → LP2
I want my result set to look like this.
[
{
"lp": "LP1",
"campaigns": [
{aId: "A1", cId: "C1"},
{aId: "A2", cId: "C1"},
{aId: "A3", cId: "C2"},
{aId: "A4", cId: "C2"}
]
},
{
"lp": "LP2",
"campaigns": [
{aId: "A5", cId: "C3"}
]
}
]
Any help would be greatly appreciated.

Something like this should work, group by the LPs and then by the paths from them.
g.V().hasLabel('LP').
group().
by(id).
by(__.in().in().path().by('aId').by('cId').fold())
Note that if possible, use the edge labels for the in() steps. This will help the query planner only pick relevant edges to traverse over.

Related

Orthogonal edges in ER diagram

I'm trying to make an Entity-relationship diagram using the Graphviz DOT language. In my model I have a self-referencing relationship and here I would like the edges to be orthogonal, i.e. consist only of vertical and horizontal lines. Currently I have this diagram:
digraph G {
edge [arrowhead = none]
Entity [shape = box]
Relationship [shape = diamond]
Entity -> Relationship [headport = w, tailport = w]
Relationship -> Entity [headport = e, tailport = e]
}
I tried adding graph [splines = ortho] but then the diagram renders like this:
Any ideas? I'm using version 2.43.0 of DOT.
The ortho implementation is rather flawed, Here is a DIY version. It adds invisible point-shaped nodes to each side of the two ER nodes and then draws edges to connect everything to look "ortho".
digraph G {
splines=false
edge [arrowhead = none]
{ rank=same
Entity [shape = box]
node [shape=point label="" style=invis]
x1 [group=G1]
x2 [group=g2]
x1 -> Entity [tailclip=false]
Entity -> x2 [headclip=false]
}
{ rank=same
Relationship [shape = diamond]
node [shape=point label="" style=invis]
y1 [group=G1]
y2 [group=g2]
y1 -> Relationship [tailclip=false]
Relationship -> y2 [headclip=false]
}
x1 -> y1 [headclip=false tailclip=false]
x2 -> y2 [headclip=false tailclip=false]
}
Giving:

How to draw diagonal edges in Graphviz

How can I draw diagonal lines between two nodes in Graphviz (Dot Language).
I want to draw the following shape.
I tried:
graph G {
V[pos="0,0"];
N[pos="40,40!"];
V -- N [label="NSUBJ"]
}
But it draws orthogonal lines. besides I want to draw multiple subgraphs with an order number as above!
It's possible to use pos attribute, but in that case you'd have to use neato and set pos for every node:
graph G {
V [pos = "0,100"]
N [pos = "50,0"]
S [pos = "200,100"]
VPC [pos = "150,0"]
NPC [pos = "250,0"]
V -- N [label="NSUBJ"]
S -- VPC
S -- NPC
}
Then use the following:
neato -n -Tpng -o test.png test.gv
The output is the following:
Also it's possible to make lines diagonal if use invisible nodes:
graph G {
node [shape=plaintext]
labelloc="b"
pencolor=transparent
subgraph cluster_1 {
label="(1)"
S_1 [label="S"]
VPC_1 [label="VPC"]
NPC_1 [label="NPC"]
V_1 [label="V"]
invis_1 [style=invis]
N_1 [label="N"]
V_1 -- invis_1 [style=invis]
V_1 -- N_1 [label="NSUBJ"]
S_1 -- VPC_1
S_1 -- NPC_1
}
subgraph cluster_2 {
label="(2)"
VPC_2 [label="VPC"]
V_2_2 [label="V"]
NPC_2 [label="NPC"]
V_2 [label="V"]
invis_2 [style=invis]
N_2 [label="N"]
V_2 -- invis_2 [style=invis]
V_2 -- N_2 [label="COPCOMP"]
VPC_2 -- V_2_2
VPC_2 -- NPC_2
}
}
Running this sequence of commands produces the following output:
ccomps -Cx test.gv | dot | gvpack -array_1 | neato -n2 -Tpng > test.png

Graphviz Draw graph nodes using BFS order

I've a graph file (.dot) with nodes that has depth and size "properties". I want to use graphviz to draw this graph considering "depth" as the depth of a Breadth First Search and the size property as a relative size of the node.
I've tried using twopi and setting all nodes that have the same depth on the same rank, but with no success. Any suggestion on how I can accomplish this?
Sample graph:
strict digraph {
root = 0;
ranksep = 5;
{rank=same;
0
14754221888142813049
}
{rank=same;
17110173155996056797
8860119836345733269
12488214955576990298
5164430016200693425
6534280015544966791
16035081712171710670
7728255721346380016
3065692608114503807
15537038826989012875
15464545769657918305
7964210557574239786
17237485240931079100
9667703542183627069
9063621412962345275
4956992700610885217
703599774521196210
}
0 [label="A"];
14754221888142813049 [label="B"];
17110173155996056797 [label="C"];
8860119836345733269 [label="D"];
12488214955576990298 [label="E"];
5164430016200693425 [label="F"];
6534280015544966791 [label="G"];
16035081712171710670 [label="H"];
7728255721346380016 [label="I"];
3065692608114503807 [label="J"];
15537038826989012875 [label="K"];
15464545769657918305 [label="L"];
7964210557574239786 [label="M"];
17237485240931079100 [label="N"];
9667703542183627069 [label="O"];
9063621412962345275 [label="P"];
4956992700610885217 [label="Q"];
703599774521196210 [label="R"];
0 -> 14754221888142813049
0 -> 12488214955576990298
0 -> 5164430016200693425 [weight=0, constraint=false];
0 -> 15537038826989012875
0 -> 7964210557574239786
0 -> 9667703542183627069
0 -> 17237485240931079100
5164430016200693425 -> 8860119836345733269 [weight=0, constraint=false];
8860119836345733269 -> 4956992700610885217
8860119836345733269 -> 9063621412962345275
8860119836345733269 -> 703599774521196210
8860119836345733269 -> 17110173155996056797
8860119836345733269 -> 6534280015544966791
8860119836345733269 -> 16035081712171710670
8860119836345733269 -> 7728255721346380016
8860119836345733269 -> 3065692608114503807
8860119836345733269 -> 15464545769657918305
}
You are trying to capture hierarchical structure so you want to use the dot layout. By default, if you have an edge a->b, node b will be 1 level below node a. If you have a tree, and make sure the node of depth 0 appears first, you'll get the layout you want by default. If your graph is more complex, the edge criteria mentioned, or cycle breaking, may interfere with what you want. In that case, you need to make the depth constraints more explicit and turn off other edge constraints. There are several ways to do this.
Suppose you have the following graph where the numbers in the node names indicate the depth.
digraph {
0 -> a1
0 -> b1
a1 -> a2
a1 -> b2
b1 -> c2
b1 -> d2
a2 -> d2
a2 -> b1
}
A simple way to get what you want is to do a BFS, and set any edge not part of the BFS tree to have constraint=false.
digraph {
0 -> a1
0 -> b1
a1 -> a2
a1 -> b2
b1 -> c2
b1 -> d2
a2 -> d2 [constraint=false]
a2 -> b1 [constraint=false]
}
Or you can use rank=same to make sure nodes are placed on ranks corresponding to their depths, again turning off edges that conflict. (This assumes you have at least one chain of edges going from depth 0 to the bottom. If not, you can introduce an invisible chain of dummy nodes and edges satisfying this, and adding each dummy node to its rank=same subgraph.}
digraph {
0 -> a1
0 -> b1
a1 -> a2
a1 -> b2
b1 -> c2
b1 -> d2
a2 -> d2 [constraint=false]
a2 -> b1 [constraint=false]
{rank=same a1 b1}
{rank=same a2 b2 c2 d2}
}
This allows the depth function to not be actually tied to a BFS tree.
By the way, twopi should have worked, but with the layout center out instead of top down, as its levels are based on a BFS from a root node. This assumes you set the root attribute and, as you have an explicit BFS in mind, turning off non-tree edges by setting weight=0.
digraph {
root=0
0 -> a1
0 -> b1
a1 -> a2
a1 -> b2
b1 -> c2
b1 -> d2
a2 -> d2 [weight=0]
a2 -> b1 [weight=0]
}

Make boxes of the same width

I'm trying to make a flowchart. In this flowchart, I want to have boxed nodes with varying labels (and thus varying label sizes), but I want the nodes to have the same size.
The source code is the following:
digraph G {
a0 [ label="this is a loooong label" ]
a3 [ label="short label" ]
b0 [ label="this is a long label" ]
b3 [ label="short label" ]
a0, a1, a2, a3 [ shape=box ]
b0, b1, b2, b3 [ shape=box ]
subgraph cluster_one {
style=filled;
color=lightgrey;
a0 -> a1 -> a2 -> a3;
label = "This is nice and grey";
}
subgraph cluster_two {
b0 -> b1 -> b2 -> b3;
label = "This is nice and white";
color=blue;
}
}
I get this image:
I want the boxes in the subgraphs to have the same width. How can I do this?
Thank you in advance :)
You can set default values for nodes via node [width=5]. this sets the minimum size. If you set fixed-size=true this will be the actual size.
You can define a global node style, like this:
digraph G {
node[width=4]
...

Showing Arbitrary Graph Nodes and Edges for a Network in GraphViz

I'd like to draw a network, as a fully connected directed graph, with arbitrary number of nodes and edges as shown in the pic.
What would be the easy way to draw this with GraphViz?
graphviz gallery has a very similar entry, with fancy graphic: it's as easy as replacing the names start, etc... with your own in the generating script. Feed it to dot program.
digraph G {bgcolor="red:cyan" gradientangle=0
subgraph cluster_0 {
style=filled;
color=lightgrey;
fillcolor="blue:yellow";
gradientangle=90;
node [fillcolor="yellow:green" style=filled gradientangle=270] a0;
node [fillcolor="green:red"] a1;
node [fillcolor="red:cyan"] a2;
node [fillcolor="cyan:blue"] a3;
a0 -> a1 -> a2 -> a3;
label = "process #1";
}
subgraph cluster_1 {
node [fillcolor="yellow:magenta"
style=filled gradientangle=270] b0;
node [fillcolor="magenta:cyan"] b1;
node [fillcolor="cyan:red"] b2;
node [fillcolor="red:blue"] b3;
b0 -> b1 -> b2 -> b3;
label = "process #2";
color=blue
fillcolor="blue:yellow";
style=filled;
gradientangle=90;
}
start -> a0;
start -> b0;
a1 -> b3;
b2 -> a3;
a3 -> a0;
a3 -> end;
b3 -> end;
start [shape=Mdiamond ,
fillcolor="yellow:brown",
gradientangle=90,
style=radial];
end [shape=Msquare,
fillcolor="orange:blue",
style=radial,
gradientangle=90];
}

Resources