UNPKG

neo4jkb

Version:

A graph knowledge base implemented in neo4j.

284 lines (263 loc) 7.44 kB
var _ = require('lomath') var Promise = require('bluebird'); var cons = require('../lib/constrain') // Assets used in unit tests // construct a graph for testing, must have: // path > 3 units // >1 degree // cycle // multiedge // A -> {1,2,3} // 1 -> 2 -> 3 -> 1 // A -> B -> C -> D -> Z // D -[:test_next_2]-> Z var labelNode = 'alpha', propA = cons.legalize({ name: 'A', hash_by: 'name' }), propB = cons.legalize({ name: 'B', hash_by: 'name' }), propC = cons.legalize({ name: 'C', hash_by: 'name' }), propD = cons.legalize({ name: 'D', hash_by: 'name' }), propZ = cons.legalize({ name: 'Z', hash_by: 'name' }), prop1 = cons.legalize({ name: 1, hash_by: 'name' }), prop2 = cons.legalize({ name: 2, hash_by: 'name' }), prop3 = cons.legalize({ name: 3, hash_by: 'name' }), propAl = cons.legalize({ name: 'A' }, 'name') propAi = { name: 'A' }, propBi = { name: 'B' }, propCi = { name: 'C' }, propDi = { name: 'D' }, propZi = { name: 'Z' }, prop1i = { name: 1 }, prop2i = { name: 2 }, prop3i = { name: 3 }, labelEdge = 'next', labelEdge2 = 'next_2', propE = cons.legalize({ name: 'E', hash_by: 'name' }), propE2 = cons.legalize({ name: 'E2', hash_by: 'name' }), propEi = { name: 'E' }, propE2i = { name: 'E2' }, distE = '*..2', user = { "id": "ID0000001", "name": "alice", "email_address": "alice@email.com", "slack": { "id": "ID0000001", "team_id": "TD0000001", "name": "alice", "deleted": false, "presence": "away" } }, neoRes = [{ "columns": ["a"], "data": [{ "row": [{ "id": "ID0000001", "name": "alice", "email_address": "alice@email.com", "slack__id": "ID0000001", "slack__team_id": "TD0000001", "slack__name": "alice", "slack__deleted": false, "slack__presence": "away", "hash_by": "id", "hash": "ID0000001", "updated_by": "bot", "updated_when": "2016-01-29T16:03:19.592Z" }, { "id": "ID0000002", "name": "bob", "email_address": "bob@email.com", "slack__id": "ID0000002", "slack__team_id": "TD0000002", "slack__name": "bob", "slack__deleted": false, "slack__presence": "away", "hash_by": "id", "hash": "ID0000002", "updated_by": "bot", "updated_when": "2016-01-29T16:03:19.594Z" }, { "id": "USLACKBOT", "name": "slackbot", "real_name": "slackbot", "email_address": null, "slack__id": "USLACKBOT", "slack__team_id": "T07S1438V", "slack__name": "slackbot", "slack__deleted": false, "slack__status": null, "slack__color": "757575", "slack__real_name": "slackbot", "slack__tz": null, "slack__tz_label": "Pacific Standard Time", "slack__tz_offset": -28800, "slack__is_admin": false, "slack__is_owner": false, "slack__is_primary_owner": false, "slack__is_restricted": false, "slack__is_ultra_restricted": false, "slack__is_bot": false, "slack__presence": "active", "hash_by": "id", "hash": "USLACKBOT", "updated_by": "bot", "updated_when": "2016-01-29T16:03:19.594Z" }] }] }] var A = { KB: require('../index')({ NEO4J_AUTH: process.env.NEO4J_AUTH }), labelNode: labelNode, propAl: propAl, propA: propA, propB: propB, propC: propC, propD: propD, propZ: propZ, prop1: prop1, prop2: prop2, prop3: prop3, propLabelA: [propA, labelNode], propLabelAl: [propAl, labelNode], propLabelB: [propB, labelNode], propLabelC: [propC, labelNode], propLabelD: [propD, labelNode], propLabelZ: [propZ, labelNode], propLabel1: [prop1, labelNode], propLabel2: [prop2, labelNode], propLabel3: [prop3, labelNode], propLabelAi: [propAi, labelNode], propLabelBi: [propBi, labelNode], propLabelCi: [propCi, labelNode], propLabelDi: [propDi, labelNode], propLabelZi: [propZi, labelNode], propLabel1i: [prop1i, labelNode], propLabel2i: [prop2i, labelNode], propLabel3i: [prop3i, labelNode], labelEdge: labelEdge, labelEdge2: labelEdge2, propE: propE, propE2: propE2, propLabelE: [propE, labelEdge], propLabelE2: [propE2, labelEdge2], propLabelEi: [propEi, labelEdge], propLabelE2i: [propE2i, labelEdge2], distLabelE: [distE, labelEdge], obj: { a: 0, b: {c: 1}, d: [2,3,4] }, user: user, neoRes: neoRes, flush: flush, clearTest: clearTest, buildGraph: buildGraph, log: log, string: string, extractRes: extractRes, extractQP: extractQP } // helper function to flush the resolved args from buildGraph function flush() { return } // clear out the test nodes function clearTest() { return new Promise(function(resolve, reject) { A.KB.query('MATCH (a) WHERE ANY(x IN labels(a) WHERE x =~ "(?i)^test_.*") DETACH DELETE a') .then(flush) .then(resolve) .catch(reject) }) } // build the graph: first clear the test, then buildNodes, buildEdges function buildGraph() { return new Promise(function(resolve, reject) { clearTest() .then(buildNodes) .then(buildEdges) // .then(A.log) .then(flush) .then(resolve) .catch(reject) }) } // build the nodes function buildNodes() { return new Promise(function(resolve, reject) { A.KB.addNode( [[A.propA, A.labelNode]], [[A.propB, A.labelNode]], [[A.propC, A.labelNode]], [[A.propD, A.labelNode]], [[A.propZ, A.labelNode]], [[A.prop1, A.labelNode]], [[A.prop2, A.labelNode]], [[A.prop3, A.labelNode]] ) // .then(A.log) .then(resolve) .catch(reject) }) } // build the edges function buildEdges() { return new Promise(function(resolve, reject) { A.KB.addEdge( // A -> {1,2,3} [[A.propA], [A.propE, A.labelEdge], [A.prop1]], [[A.propA], [A.propE, A.labelEdge], [A.prop2]], [[A.propA], [A.propE, A.labelEdge], [A.prop3]], // 1 -> 2 -> 3 -> 1 [[A.prop1], [A.propE, A.labelEdge], [A.prop2]], [[A.prop2], [A.propE, A.labelEdge], [A.prop3]], [[A.prop3], [A.propE, A.labelEdge], [A.prop1]], // A -> B -> C -> D -> Z [[A.propA], [A.propE, A.labelEdge], [A.propB]], [[A.propB], [A.propE, A.labelEdge], [A.propC]], [[A.propC], [A.propE, A.labelEdge], [A.propD]], [[A.propD], [A.propE, A.labelEdge], [A.propZ]], // D -[:test_next_2]-> Z [[A.propD], [A.propE2, A.labelEdge2], [A.propZ]] ) // .then(A.log) .then(resolve) .catch(reject) }) } // Simple log for the first argument after JSON.stringify it. Returns the string. function log(arg) { var str = JSON.stringify(arg) console.log(str) return str; } // Shorthand to JSON.stringify the argument. Use in place of log to not log to output. function string(arg) { return JSON.stringify(arg) } // extract neoRes. function extractRes(neoRes) { return _.map(neoRes, extractOneRes) } // extract a single neoRes object. function extractOneRes(obj) { // use assign var data = obj.data; var extract = _.map(data, function(o) { return _.map(_.flattenDeep(_.get(o, 'row')), function(row){ return _.get(row, 'name') || row }) }) var sorted = extract.sort() _.assign(obj, { data: sorted }) return obj } // extract a query-param pair function extractQP(arr) { var query = arr[0], param = arr[1] param = _.mapValues(param, function(prop) { return _.omit(prop, ['updated_when', 'created_when']) }) return [query, param] } module.exports = A;