diff --git a/__mocks__/neo4j.js b/__mocks__/neo4j.js index 7ff5d53e26c..998ff141428 100644 --- a/__mocks__/neo4j.js +++ b/__mocks__/neo4j.js @@ -18,4 +18,22 @@ * along with this program. If not, see . */ -module.exports = {} +var out = { + v1: { + types: { + Node: function Node (id) { + this.identity = id + }, + Relationship: function Relationship (id) { + this.identity = id + }, + Path: function Path () {} + } + } +} + +out.v1.types.Node.prototype.toString = function () { return 'node' } +out.v1.types.Relationship.prototype.toString = function () { return 'rel' } +out.v1.types.Path.prototype.toString = function () { return 'path' } + +module.exports = out diff --git a/src/shared/services/bolt/boltMappings.js b/src/shared/services/bolt/boltMappings.js index a97adfd346d..7cddd7fe448 100644 --- a/src/shared/services/bolt/boltMappings.js +++ b/src/shared/services/bolt/boltMappings.js @@ -142,6 +142,7 @@ export function extractNodesAndRelationshipsFromRecordsForOldVis (records, types } else { records.forEach((record) => { let graphItems = keys.map((key) => record.get(key)) + graphItems = flattenArray(recursivelyExtractGraphItems(types, graphItems)).filter((item) => item !== false) rawNodes = [...rawNodes, ...graphItems.filter((item) => item instanceof types.Node)] rawRels = [...rawRels, ...graphItems.filter((item) => item instanceof types.Relationship)] let paths = graphItems.filter((item) => item instanceof types.Path) @@ -161,6 +162,26 @@ export function extractNodesAndRelationshipsFromRecordsForOldVis (records, types return { nodes: nodes, relationships: relationships } } +const recursivelyExtractGraphItems = (types, item) => { + if (item instanceof types.Node) return item + if (item instanceof types.Relationship) return item + if (item instanceof types.Path) return item + if (Array.isArray(item)) return item.map((i) => recursivelyExtractGraphItems(types, i)) + if (['number', 'string', 'boolean'].indexOf(typeof item) !== -1) return false + if (item === null) return false + if (typeof item === 'object') { + return Object.keys(item).map((key) => recursivelyExtractGraphItems(types, item[key])) + } + return item +} + +const flattenArray = (arr) => { + return arr.reduce((all, curr) => { + if (Array.isArray(curr)) return all.concat(flattenArray(curr)) + return all.concat(curr) + }, []) +} + const extractNodesAndRelationshipsFromPath = (item, rawNodes, rawRels) => { let paths = Array.isArray(item) ? item : [item] paths.forEach((path) => { diff --git a/src/shared/services/bolt/boltMappings.test.js b/src/shared/services/bolt/boltMappings.test.js index 7f7e630dabd..c1bfc51b7ba 100644 --- a/src/shared/services/bolt/boltMappings.test.js +++ b/src/shared/services/bolt/boltMappings.test.js @@ -18,12 +18,13 @@ * along with this program. If not, see . */ -/* global test, expect */ +/* global describe, test, expect */ import { v1 as neo4j } from 'neo4j-driver-alias' import { itemIntToString, arrayIntToString, extractNodesAndRelationshipsFromRecords, + extractNodesAndRelationshipsFromRecordsForOldVis, extractPlan, flattenProperties, objIntToString @@ -329,4 +330,41 @@ describe('boltMappings', () => { expect(flattenedProperties).toEqual(result) }) }) + describe('extractNodesAndRelationshipsFromRecordsForOldVis', () => { + test('should recursively look for graph items', () => { + // Given + const firstNode = new neo4j.types.Node('1', ['Person'], {prop1: 'prop1'}) + const nodeCollection = [ + new neo4j.types.Node('2', ['Person'], {prop1: 'prop1'}), + new neo4j.types.Node('3', ['Person'], {prop1: 'prop1'}), + new neo4j.types.Node('4', ['Person'], {prop1: 'prop1'}) + ] + const boltRecord = { + keys: ['n', 'c'], + get: (key) => { + if (key === 'n') { + return firstNode + } + if (key === 'c') { + return nodeCollection + } + } + } + const records = [boltRecord] + + // When + const out = extractNodesAndRelationshipsFromRecordsForOldVis( + records, + neo4j.types, + false, + { + intChecker: () => true, + intConverter: (a) => a + } + ) + + // Then + expect(out.nodes.length).toEqual(4) + }) + }) })