Skip to content

Commit

Permalink
G 3.4 update to gremlin 3.4 (#68)
Browse files Browse the repository at this point in the history
* adapt to gremlin 3.4

* Added multi-version support and node properties scrolling (#63)

* better compatibility with gremlin 3.3 and 3.4
  • Loading branch information
bricaud authored Aug 15, 2019
1 parent 5f03f35 commit 62a4839
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 73 deletions.
16 changes: 11 additions & 5 deletions graphexp.html
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ <h1 class="header-heading">Graph Explorer v 0.6</h1>

<div class="aside right_bar" id="details" style="background-color:transparent;pointer-events:auto;">
<div id="messageArea"></div><div id="outputArea"></div>
<div id="nodeInfo" style="background-color:transparent;pointer-events:none;">
<div id="nodeInfo" style="background-color:transparent;overflow:scroll; height:400px;">
</div>
</div>
<!--
Expand Down Expand Up @@ -151,6 +151,7 @@ <h1 class="header-heading">Graph Explorer v 0.6</h1>
<div class="nav input_unit_container">
<label for="communication_method">Gremlin version:</label>
<select name="communication_method" id="communication_method">
<option value="GraphSON3_4">3.4.*</option>
<option value="GraphSON3">3.3.*</option>
<option value="GraphSON2">3.2.*</option>
</select>
Expand Down Expand Up @@ -389,11 +390,16 @@ <h1 class="header-heading">Graph Explorer v 0.6</h1>
function get_prop_value(d,prop_name,item){
//let COMMUNICATION_METHOD = $('#communication_method').val();
if (prop_name in d.properties){
prop_value = d.properties[prop_name]
if (item=='nodes'){
if ('summary' in d.properties[prop_name]) {
return d.properties[prop_name]['summary'];
} else if (COMMUNICATION_METHOD == 'GraphSON1') {
return d.properties[prop_name][0].value;
if (typeof prop_value === "string"){
return prop_value;
} else {
if ('summary' in prop_value) {
return prop_value['summary'];
} else if (COMMUNICATION_METHOD == 'GraphSON1') {
return prop_value[0].value;
}
}
}
else if (item=='edges'){
Expand Down
13 changes: 9 additions & 4 deletions scripts/graph_viz.js
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,10 @@ var graph_viz = (function () {
_svg.selectAll("*").remove();
_Nodes = [], _Links = [];
layers.clear_old();
_simulation = {};
_simulation = {};

// clear DB table
$('#tableDBDetails tbody').empty()
}


Expand Down Expand Up @@ -400,8 +403,10 @@ var graph_viz = (function () {
var _nodes = node_deco.merge(all_nodes);




var focus_node_data = d3.select(".focus_node").data();
if (focus_node_data.length > 0){
infobox.display_info(focus_node_data[0]);
}
//////////////////////////////////
// Additional clean up
graphShapes.decorate_old_elements(layers.depth());
Expand Down Expand Up @@ -533,8 +538,8 @@ var graph_viz = (function () {
_svg.selectAll(".old_edge" + stop_layer).remove();
_svg.selectAll(".old_edgepath" + stop_layer).remove();
_svg.selectAll(".old_edgelabel" + stop_layer).remove();
infobox.display_info(d);
graphioGremlin.click_query(d);
//infobox.display_info(d);
console.log('event!!')
}
}
Expand Down
134 changes: 96 additions & 38 deletions scripts/graphioGremlin.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,15 @@ var graphioGremlin = (function(){


function search_query() {
// Query sent to the server when clicking the search button
//
// Preprocess query
let input_string = $('#search_value').val();
let input_field = $('#search_field').val();
let label_field = $('#label_field').val();
let limit_field = $('#limit_field').val();
let search_type = $('#search_type').val();
let search_type = $('#search_type').val();
let communication_method = $('#communication_method').val();
//console.log(input_field)
var filtered_string = input_string;//You may add .replace(/\W+/g, ''); to refuse any character not in the alphabet
if (filtered_string.length>50) filtered_string = filtered_string.substring(0,50); // limit string length
Expand Down Expand Up @@ -121,14 +124,17 @@ var graphioGremlin = (function(){
}

let gremlin_query_nodes = "nodes = " + traversal_source + ".V()" + has_str;
// Query limit
if (limit_field !== "" && isInt(limit_field) && limit_field > 0) {
gremlin_query_nodes += ".limit(" + limit_field + ").toList();";
} else {
gremlin_query_nodes += ".toList();";
}
gremlin_query_nodes += ".limit(" + limit_field + ")";
} else {
console.log('Warning: no node limit set for the query. The query may fail if the graph is too big.')
}
gremlin_query_nodes += ".toList();";

let gremlin_query_edges = "edges = " + traversal_source + ".V(nodes).aggregate('node').outE().as('edge').inV().where(within('node')).select('edge').toList();";
let gremlin_query_edges_no_vars = "edges = " + traversal_source + ".V()"+has_str+".aggregate('node').outE().as('edge').inV().where(within('node')).select('edge').toList();";
//let gremlin_query_edges_no_vars = "edges = " + traversal_source + ".V()"+has_str+".bothE();";
let gremlin_query_edges_no_vars = "edges = " + traversal_source + ".V()"+has_str+".aggregate('node').outE().as('edge').inV().where(within('node')).select('edge').toList();";
//let gremlin_query_edges_no_vars = "edges = " + traversal_source + ".V()"+has_str+".bothE();";
let gremlin_query = gremlin_query_nodes + gremlin_query_edges + "[nodes,edges]";
console.log(gremlin_query);

Expand Down Expand Up @@ -161,15 +167,30 @@ var graphioGremlin = (function(){
!isNaN(parseInt(value, 10));
}
function click_query(d) {
var edge_filter = $('#edge_filter').val();
// Gremlin query
//var gremlin_query = traversal_source + ".V("+d.id+").bothE().bothV().path()"
// 'inject' is necessary in case of an isolated node ('both' would lead to an empty answer)
// Query sent to the server when a node is clicked
//
var edge_filter = $('#edge_filter').val();
var communication_method = $('#communication_method').val();
var id = d.id;
if(isNaN(id)){ // Add quotes if id is a string (not a number).
id = '"'+id+'"';
}
var gremlin_query_nodes = 'nodes = ' + traversal_source + '.V('+id+').as("node").both('+(edge_filter?'"'+edge_filter+'"':'')+').as("node").select(all,"node").inject(' + traversal_source + '.V('+id+')).unfold()'
// Gremlin query
var gremlin_query_nodes = 'nodes = ' + traversal_source + '.V('+id+').as("node").both('+(edge_filter?'"'+edge_filter+'"':'')+').as("node").select(all,"node").unfold()'
// Variant depending on the Gremlin version
if (communication_method == "GraphSON3_4") {
// Version 3.4
gremlin_query_nodes += ".valueMap().with(WithOptions.tokens)";
gremlin_query_nodes += 'fold().inject(' + traversal_source + '.V(' + id + ').valueMap().with(WithOptions.tokens)).unfold()';
} else {
gremlin_query_nodes += 'fold().inject(' + traversal_source + '.V(' + id + ')).unfold()';
}
//var gremlin_query_nodes = 'nodes = ' + traversal_source + '.V('+id+').as("node").both('+(edge_filter?'"'+edge_filter+'"':'')+').as("node").select(all,"node").unfold().valueMap()'
//gremlin_query_nodes += 'fold().inject(' + traversal_source + '.V('+id+').valueMap()).unfold()'

// 'inject' is necessary in case of an isolated node ('both' would lead to an empty answer)
console.log('Query for the node and its neigbhors')
console.log(gremlin_query_nodes)
var gremlin_query_edges = "edges = " + traversal_source + ".V("+id+").bothE("+(edge_filter?"'"+edge_filter+"'":"")+")";
var gremlin_query = gremlin_query_nodes+'\n'+gremlin_query_edges+'\n'+'[nodes.toList(),edges.toList()]'
// while busy, show we're doing something in the messageArea.
Expand Down Expand Up @@ -355,7 +376,7 @@ var graphioGremlin = (function(){
return // TODO handle answer to check if data has been written
}
//console.log(COMMUNICATION_METHOD)
if (COMMUNICATION_METHOD == 'GraphSON3'){
if (COMMUNICATION_METHOD == 'GraphSON3' || COMMUNICATION_METHOD == 'GraphSON3_4'){
//console.log(data)
data = graphson3to1(data);
var arrange_data = arrange_datav3;
Expand Down Expand Up @@ -481,30 +502,67 @@ var graphioGremlin = (function(){
return data_dic
}

function extract_infov3(data) {
var data_dic = {id:data.id, label:data.label, type:data.type, properties:{}}
var prop_dic = data.properties
//console.log(prop_dic)
for (var key in prop_dic) {
if (prop_dic.hasOwnProperty(key)) {
if (data.type == 'vertex'){// Extracting the Vertexproperties (properties of properties for vertices)
var property = prop_dic[key];
property['summary'] = get_vertex_prop_in_list(prop_dic[key]).toString();
} else {
var property = prop_dic[key]['value'];
}
//property = property.toString();
data_dic.properties[key] = property;
// If a node position is defined in the DB, the node will be positioned accordingly
// a value in fx and/or fy tells D3js to fix the position at this value in the layout
if (key == node_position_x) {
data_dic.fx = prop_dic[node_position_x]['0']['value'];
}
if (key == node_position_y) {
data_dic.fy = prop_dic[node_position_y]['0']['value'];
}
}
}
function extract_infov3(data) {
var isGraphSON3_4 = ($('#communication_method').val() == "GraphSON3_4");
var data_dic = { id: data.id, label: data.label, type: data.type, properties: {} };
var prop_dic = {};
// VERSION 3.4
if (isGraphSON3_4) {

for (var key in data) {
if (data.hasOwnProperty(key) && key != 'id' && key != 'label' && key != 'type') prop_dic[key] = data[key];
}
//var prop_dic = data.properties
//console.log(prop_dic)
for (var key in prop_dic) {
if (prop_dic.hasOwnProperty(key)) {
if (data.type == 'vertex') {// Extracting the Vertexproperties (properties of properties for vertices)
var property = prop_dic[key].toString();
//property['summary'] = get_vertex_prop_in_list(prop_dic[key]).toString();
//property = get_vertex_prop_in_list(prop_dic[key]).toString();
} else {
var property = prop_dic[key];//['value'];
}
//console.log('key - Property:')
//console.log(key,property)
//property = property.toString();
data_dic.properties[key] = property;
// If a node position is defined in the DB, the node will be positioned accordingly
// a value in fx and/or fy tells D3js to fix the position at this value in the layout
if (key == node_position_x) {
data_dic.fx = prop_dic[node_position_x]['0']['value'];
}
if (key == node_position_y) {
data_dic.fy = prop_dic[node_position_y]['0']['value'];
}
}
}
}
else {
// NOT VERSION 3.4
prop_dic = data.properties;
//console.log(prop_dic)
for (var key2 in prop_dic) {
if (prop_dic.hasOwnProperty(key2)) {
if (data.type == 'vertex'){// Extracting the Vertexproperties (properties of properties for vertices)
var property2 = prop_dic[key2];
property2['summary'] = get_vertex_prop_in_list(prop_dic[key2]).toString();
} else {
var property2 = prop_dic[key2]['value'];
}
//property = property.toString();
data_dic.properties[key2] = property2;
// If a node position is defined in the DB, the node will be positioned accordingly
// a value in fx and/or fy tells D3js to fix the position at this value in the layout
if (key2 == node_position_x) {
data_dic.fx = prop_dic[node_position_x]['0']['value'];
}
if (key2 == node_position_y) {
data_dic.fy = prop_dic[node_position_y]['0']['value'];
}
}
}
}
if (data.type=="edge"){
data_dic.source = data.outV;
data_dic.target = data.inV;
Expand All @@ -515,7 +573,7 @@ var graphioGremlin = (function(){
}
}
}
return data_dic
return data_dic;
}

function get_vertex_prop_in_list(vertexProperty){
Expand Down
63 changes: 37 additions & 26 deletions scripts/infobox.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ var infobox = (function(){
////////////////////////
// Public function
function create(label_graph,label_graphElem){
var graph_bar = d3.select(label_graph);
graph_bar.append("h2").text("Graph Info")
var graph_bar = d3.select(label_graph);
graph_bar.append("h2").text("Graph Info");
_table_Graphinfo = graph_bar.append("table").attr("id","tableGraph");
init_table(_table_Graphinfo,["Type","Count"]);

var graphElem_bar = d3.select(label_graphElem);
graphElem_bar.append("h2").text("Item Info")
graphElem_bar.append("h2").text("Item Info");
_table_IDinfo = graphElem_bar.append("table").attr("id","tableIdDetails");
init_table(_table_IDinfo,["Key","Value"]);
_table_DBinfo = graphElem_bar.append("table").attr("id","tableDBDetails");
Expand All @@ -49,16 +49,16 @@ var infobox = (function(){
var row = table_head.append("tr");
for (var key in entries){
row.append("th").text(entries[key]);
}
var table_body = table_handle.append("tbody");
}
var table_body = table_handle.append("tbody");
var row = table_body.append("tr");
for (var key in entries){
row.append("td").text("");
}
}

function display_graph_info(data){
_table_Graphinfo.select("tbody").remove();
_table_Graphinfo.select("tbody").remove();
var info_table = _table_Graphinfo.append("tbody");
var data_to_display = data[0][0];
append_keysvalues(info_table,{"Node labels":""},"bold");
Expand Down Expand Up @@ -118,10 +118,12 @@ var infobox = (function(){
}


function _display_DBinfo(d){
_table_DBinfo.select("tbody").remove();
var info_table = _table_DBinfo.append("tbody");
function _display_DBinfo(d) {
_table_DBinfo.select("tbody").remove();
var info_table = _table_DBinfo.append("tbody");
if (d.type=='vertex'){
//console.log('display node data')
//console.log(d)
for (var key in d.properties){
_display_vertex_properties(key,d.properties[key],info_table)
}
Expand All @@ -137,24 +139,33 @@ var infobox = (function(){
}

function _display_vertex_properties(key,value,info_table) {
for (var subkey in value){
// Ignore the summary field, which is set in graphioGremlin.extract_infov3()
if (subkey === "summary") {
continue;
if (typeof value === "string" && $('#communication_method').val() =="GraphSON3_4"){
var new_info_row = info_table.append("tr");
new_info_row.append("td").text(key).style("font-size",_font_size);
new_info_row.append("td").text(value).style("font-size",_font_size);
new_info_row.append("td").text('').style("font-size",_font_size);
}
else
{
for (var subkey in value){
// Ignore the summary field, which is set in graphioGremlin.extract_infov3()
if (subkey === "summary") {
continue;
}
if ( ((typeof value[subkey] === "object") && (value[subkey] !== null)) && ('properties' in value[subkey]) ){
for (var subsubkey in value[subkey].properties){
var new_info_row = info_table.append("tr");
new_info_row.append("td").text(key).style("font-size",_font_size);
new_info_row.append("td").text(value[subkey].value).style("font-size",_font_size);
new_info_row.append("td").text(subsubkey + ' : '+ value[subkey].properties[subsubkey]).style("font-size",_font_size);
}
} else {
var new_info_row = info_table.append("tr");
new_info_row.append("td").text(key).style("font-size",_font_size);
new_info_row.append("td").text(value[subkey].value).style("font-size",_font_size);
new_info_row.append("td").text('').style("font-size",_font_size);
}
}
if ( ((typeof value[subkey] === "object") && (value[subkey] !== null)) && ('properties' in value[subkey]) ){
for (var subsubkey in value[subkey].properties){
var new_info_row = info_table.append("tr");
new_info_row.append("td").text(key).style("font-size",_font_size);
new_info_row.append("td").text(value[subkey].value).style("font-size",_font_size);
new_info_row.append("td").text(subsubkey + ' : '+ value[subkey].properties[subsubkey]).style("font-size",_font_size);
}
} else {
var new_info_row = info_table.append("tr");
new_info_row.append("td").text(key).style("font-size",_font_size);
new_info_row.append("td").text(value[subkey].value).style("font-size",_font_size);
new_info_row.append("td").text('').style("font-size",_font_size);
}
}
}

Expand Down

0 comments on commit 62a4839

Please sign in to comment.