Skip to content

Construct graphs with multiple node/edge types and helpers to perform selective traversals and calculations.

Notifications You must be signed in to change notification settings

electronifie/graph-calc

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

34 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Build Status

Getting started

Install npm install graph-calc --save

Test npm test

Generate Docs npm run doc


Constructing the graph

Setup

A more complete setup can be found here.

var Edge = require('graph-calc').Edge;
var Factory = require('graph-calc').Factory;
var Graph = require('graph-calc').Graph;
var Node = require('graph-calc').Node;
var util = require('util');

/* create node types */

var TeacherNode = function (options) {
  this.id = this.type + '-' + options.raw.id;
  Node.call(this, options);
};
util.inherits(TeacherNode, Node);
TeacherNode.prototype.type = 'teacher';

var ClassNode = function (options) {
  this.id = this.type + '-' + options.raw.id;
  Node.call(this, options);
};
util.inherits(ClassNode, Node);
ClassNode.prototype.type = 'class';

/* create an edge type */

var TeachesEdge = function (options) {
  this.id = this.type + '-' + options.raw.teacher.id + '-' + options.raw.class.id;
  this.fromNode = options.factory.createOrUpdateNode(this.fromNodeType, options.raw.teacher);
  this.toNode = options.factory.createOrUpdateNode(this.toNodeType, options.raw.class);
  Edge.call(this, options);
};
util.inherits(TeachesEdge, Edge);
TeachesEdge.prototype.fromNodeType = 'teacher';
TeachesEdge.prototype.type = 'teaches';
TeachesEdge.prototype.toNodeType = 'class';
TeachesEdge.raw2id = function (raw) { return TeachesEdge.prototype.type + '-' + raw.teacher.id + '-' + raw.class.id };

/* create the graph, registering the nodes/edges via a Factory */

var schoolGraph = new Graph ({
  factory: new Factory({
    nodeClasses: [ TeacherNode, ClassNode ],
    edgeClasses: [ TeachesEdge ]
  });
});

Node / Edge creation

Create an edge, automatically creating the node if it doesn't exist (more examples):

  schoolGraph.factory.createOrUpdateEdge('teaches', { teacher: { id: 'Sue' }, class: { id: 'Chemistry' } });
  schoolGraph.factory.createOrUpdateEdge('teaches', { teacher: { id: 'Sue' }, class: { id: 'Physics' } });

Traversal

Traverse the full graph (more examples):

var Traverser = require('graph-calc').Traverser;

var startNode = graph.factory.getNode('teacher', 'teacher-Sue');
var traverser = new Traverser({
  onVisitNode: function (node, meta) {
    var path = meta.path;
    var depth = meta.depth;
    var viaEdge = meta.viaEdge;
    var previouslyVisited = meta.previouslyVisited;
    ...
  },
  onTraverseEdge: function (edge) { ... },
  // Other options:
  // onlyNodeTypes: ['teacher', 'student', ...],
  // onlyEdgeTypes: ['teaches', ...],
  // excludeNodeTypes: ['teacher', ...],
  // excludeEdgeTypes: ['teaches', ...],
  // maxDepth: 3,
  // allowLoops: true,
  // shouldVisitNode: function (node) { return true; },
  // shouldTraverseEdge: function (edge) { return true; },
});
traverser.traverse(startNode);

Traverse along a path of edge types (more examples):

var PathTraverser = require('graph-calc').PathTraverser;

var traverser = new PathTraverser({
  path: [ 'teaches' /* -> CLASS */, 'attendedBy' /* -> STUDENT */ ],
  onLeafNode: function (node, meta) { ... }
});
traverser.traverse(teacherNode);

Calculation

Perform relationship-based calculations, and queries of the graph aided by lodash (more examples):

var Calculator = require('graph-calc').Calculator;

var classByDepartmentCalculator = new Calculator({ acceptsNodeType: 'student' })
  .start()
    .withNodes({ path: ['attends' /* -> CLASS */, 'providedBy' /* -> DEPARTMENT */], revisitNodes: true })
    .map(function (node) { return node.id; })
    .countBy()
  .finish();

var teacherStudentCalculator = new Calculator({ acceptsNodeType: 'teacher' })
  .start()
    .withNodes({ path: ['teaches' /* -> CLASS */, 'attendedBy' /* -> STUDENT */], revisitNodes: false })
    .mapAndIndexCalc(classByDepartmentCalculator)
  .finish();

var result = teacherStudentCalculator.calculate(targetNode);

// e.g result:
// {
//   'student-Bobby': {
//     'department-Science': 2,
//     'department-Art': 1
//   },
//   'student-Jo': {
//     'department-Science': 4
//   }
// }

Events

Subscribe to events within a node's network (more examples):

  var NetworkSubscriber = require('graph-calc').NetworkSubscriber;
  
  // Subscribe to all the 'grade-added' and 'report-due' (fictional) events for
  // all student's taught by a teacher.
  new NetworkSubscriber({
    node: graph.factory.getNode('teacher', 'teacher-Sue'),
    
    // Define the network
    maxDepth: 3,
    onlyEdgeTypes: ['teaches', 'attendedBy'],
    
    // Attach the listeners
    nodeEvents: {
      'grade-added': function (grade) { ... },
      'report-due': function (reportName) { ... }
    }
  });

About

Construct graphs with multiple node/edge types and helpers to perform selective traversals and calculations.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published