patrickmcelwee / ml-visjs-graph-ng

graph visualization for triples stored in MarkLogic, based on the VisJS Network library
Other
4 stars 2 forks source link

MarkLogic VisJS Graph Visualization

This AngularJS library allows you to easily produce a graph visualization for triples stored in MarkLogic, based on the VisJS Network library. It is specifically designed with applications generated by the MarkLogic SlushJS generator in mind.

Getting Started

Install this library:

bower install ml-visjs-graph-ng --save

If you want to use the default graphSearch and graphExpand functions, which return the node and link data powering the graph, you need to install the mlpm module (if you want to create your own, you could use this mlpm_module code as a starting point or roll your own):

npm install -g mlpm
mlpm install visjs-graph --save
mlpm deploy -H localhost -P 8040 -u admin -p admin

Enable the triple index

Since this library works based on SPARQL queries against triples stored in your MarkLogic database, you need to enable the triple index. Note that the triple index is enabled by default starting with MarkLogic 9.0.

Using Roxy

You should do this in deploy/ml-config.xml of your application. Add the following line to the <database></database> configuration for the database with name <database-name>${content-db}</database-name> (around line 179 at the time of this writing).

      <triple-index>true</triple-index>

Using ml-gradle

Update the src/main/ml-config/databases/content-database.json file for your application to include the following property:

  "triple-index": true

Example Implementation

Add the ml.visjsGraph module as a dependency to your app.module. For example, in a slush-generated app, add this to ui/app/app.js:

angular.module('app', [
   # ...
  'ml.visjsGraph',
  # ...
]);

You can add a VisJS graph for a document by adding the following HTML snippet to a template, for example to ui/app/detail/detail.html:

<ml-visjs-graph uris="[$ctrl.uri]"></ml-visjs-graph>

NOTE: Support for multiple uris is not yet provided, but that future extension is anticipated by this API. For now, it will only initialize the graph visualization with the first uri in the list provided to the directive.

Override VisJS graphOptions

VisJS provides a robust set of options to change how your graph is displayed. We have specified a default set of options in the visjsGraphCtrl. You can override these by passing an object to graph-options in the ml-visjs-graph directive. (Only the specific options you name will be changed. If you want to return to the VisJS default for an option that we have set in the visjsGraphCtrl, you will have to specify that explicitly.)

For example:

<ml-visjs-graph uris="[$ctrl.uri]" graph-options="{edges: {color: 'red'}, nodes: {color: {background: 'orange'}}}"></ml-visjs-graph>

VisJS graphEvents

Default Behaviors

The default event hooks for this library are:

Override or extend VisJS graphEvents

VisJS also provides many event hooks for you to add behavior or draw on the canvas. We have specified several in the visjsGraphCtrl. You can override these or add additional event hooks by passing an object to graph-events in the ml-visjs-graph directive. (If you want to remove one of the event hooks defined in this library, you will have to specify an empty, 'no-op' function.)

For example, create something like this in your controller:

$scope.myEvents = {
  stabilized: function() {
    console.log('overrode stabilized event to remove auto-fitting behavior');
  },
  hold: function(params) {
    console.log('you are holding something: ', params);
  }
};

Then, in your template:

<ml-visjs-graph uris="[$ctrl.uri]" graph-events="myEvents"></ml-visjs-graph>

Get access to the VisJS network object in your controller

With two steps, you can get access to the VisJS network object in your controller (which is useful for calling methods, often in VisJS graphEvents).

  1. Add an onload event to your VisJS graphEvents).
ctrl.myEvents = {
  onload: function(network) {
    ctrl.visjsNetwork = network;
  }
};
  1. Hook up a bidirectional binding on network:
<ml-visjs-graph uris="[$ctrl.uri]" network="$ctrl.visjsNetwork" graph-events="$ctrl.myEvents"></ml-visjs-graph>

Get access to the VisJS nodes and edges

This can be useful if you want to add or delete nodes and edges. It can also be useful if you want to watch for changes in order to take some other action (such as clustering some set of nodes together).

To do this, simply bind an object in your controller to items in the ml-visjs-graph directive scope:

<ml-visjs-graph uris="[$ctrl.uri]" items="$ctrl.visjsItems"></ml-visjs-graph>

The ctrl.visjsItems object is now an object containing nodes and items pointing to VisJS Data Sets.

Specify Layout

You can specify which layout you want, by passing in layout="'hierarchyTop'". The default is 'standard'.

Specify Physics

You can also specify a different physics for the 'standard' (default) layout: physics="'barnesHut'"

Or turn off physics initially with physics="false".

Override default graphSearch and graphExpand

You can override the default graphSearch and/or graphExpand in order to provide custom data provider. functions Specify them in the directive:

<ml-visjs-graph uris="[$ctrl.uri]" graph-search="myGraphSearch" graph-expand="myGraphExpand"></ml-visjs-graph>

Both methods should return a promise that resolves to an object with two properties, nodes and edges, each containing an array. The expand function does not need to provide a full picture of the graph nodes and edges. Each node/edge it does return will either be updated or added. Existing nodes and edges will not be removed. This is a canned example that would work as a replacement for either graphSearch or graphExpand:

function cannedSearch(uris) {
  return $q.when({
    nodes: [
      {
        id: '1',
        label: 'The Number 1!',
        group: 'number', // optional
        linkCount: 8 // we look for this to add an small orb to the icon
      },
      {
        id: '2',
        label: 'The Only Even Prime!',
        group: 'number', // optional
        linkCount: 16 // we look for this to add an small orb to the icon
      }
    ],
    edges: [
      {
        id: 'more-2-1',
        label: 'moreThan',
        from: '2',
        to: '1'
      }
    ]
  });
}

See the VisJS nodes and edges documentation for additional VisJS properties you can add. You may also add additional, non-VisJS properties if you wish (for example, to provide content to a summary pane when a node is clicked).

The default functions are provided by the visjsGraphService, which simply calls a MarkLogic REST extension called visjs. (This offers an additional way to override the built-in functionality, by creating a different 'visjs' REST extension.)

More Information

I recommend becoming familiar with the documentation for a VisJS network.

Sample Data

The original slush-generated app comes with 3000 JSON documents representing people. For the moment, those documents do not include triples.

This code repository has the same JSON documents, enriched with triples representing foaf:knows relationships, an rdf:type, and an rdfs:label for each document. One document also includes a rdfs:label for foaf:knows, so that it displays on the graph as 'knows' rather than the more verbose 'foaf:knows'. To use, you can replace the original sample-data.zip file in the slush-generated app with the sample-data.zip file in this project. (Eventually, the slush-generated app may use this project's version with triples.)

Then, you can load them with (MLCP)[https://docs.marklogic.com/guide/ingestion/content-pump] like this:

./ml local mlcp -options_file import-sample-data.options

Or on Windows:

ml.bat local mlcp -options_file import-sample-data.options

Directives Provided

ml-visjs-graph

TODO