0.0.76 • Published 1 year ago

ganister-cypher-reporter v0.0.76

Weekly downloads
-
License
ISC
Repository
-
Last release
1 year ago

Logo

Codeship Status for Ganister/ganister-cypher-reporter

ganister-cypher-reporter

Report nodejs library for graph db supporting cypher

Install

Using npm:

npm i ganister-cypher-reporter

Usage

To produce a report you need the following elements :

  • an array of cypher queries
  • a report template
  • an output option (html/pdf)
  • a neo4j driver authentified instance
const reporter = require('ganister-cypher-reporter');
await reporter.buildReport({
   queries, 
   template, 
   output: 'html', 
   cypherDriver 
});

Cypher Queries

Cypher queries have to be identified with a unique id. Cypher queries can return paths, nodes, relationships or just values

Sample :

const queries = [
  {
    id: 'docs',
    query: `MATCH (d:document) 
    OPTIONAL MATCH (d)-[]->(f:file) 
    OPTIONAL MATCH (d)<-[r]-(p:part) 
    RETURN d as documents, f as files, r as docparts, p as parts ORDER BY documents._createdOn`,
  },
  {
    id: 'partCount',
    query: `MATCH (a:part) WHERE NOT(a)<-[:revises]-() RETURN COUNT(a) as partCount`,
  },
  {
    id: 'userCount',
    query: `MATCH (a:user) RETURN COUNT(a) as userCount`,
  },
  {
    id: 'partBom',
    query: `MATCH p=(a:part{_id:'1'})-[:consumes*]->(items:part) 
            OPTIONAL MATCH (items)-[partDocRel]->(documents:document)
            OPTIONAL MATCH (documents)-[docFileRel]->(file:file)
            RETURN p,partDocRel,documents,docFileRel,file`,
  }
];

Report Template

Report Template Schema :

const optionsSchema = Joi.object({
  queries: Joi.array().required().items(Joi.object({
    id: Joi.string().required(),
    query: Joi.string().required(),
    ordering: Joi.array(),
    structure: Joi.array().items(Joi.object({
      identifier: Joi.string(),
      children: Joi.array().items(Joi.object({
        identifier: Joi.string(),
        pick: Joi.string().allow('last', 'path'),
        children: Joi.array().items(Joi.link('#structureNodeType')),
      })),
    }).id('structureNodeType')),
  })),
  template: Joi.object({
    name: Joi.string().required(),
    locale: Joi.string().required(),
    indentationColumns: Joi.number(),
    author: Joi.string().required(),
    items: Joi.array().items(Joi.object({
      id: Joi.number().required(),
      type: Joi.string().allow('field', 'table', 'graph').required(),
      datatype: Joi.string(),
      mapping: Joi.string(),
      inlineRelationships: Joi.array().items(Joi.string()),
      columns: Joi.array().items(Joi.object({
        graphType: Joi.string(),
        indentation: Joi.boolean(),
        fields: Joi.object(),
        label: Joi.string(),
        category: Joi.string(),
        width: Joi.number(),
        relationships: Joi.array(),
        nodes: Joi.array(),
        columns: Joi.array().items(Joi.link('#column')),
        style: Joi.object(), // cell style
        css: Joi.object(), // header style
      }).id('column')),
      style: Joi.object(), // cell style
      width: Joi.string().allow('1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'),
      title: Joi.string(),
    })),
  }).required(),
  output: Joi.string().allow('pdf', 'html'),
  cypherDriver: Joi.object().required(),
  dataConverters: Joi.object(),
});

Template item properties

ParametersExplanation

Column properties

ParametersExplanation
inlineRelationshipsIn the report template you can define an array of relationships which will be handled as inlineRelationships in a table. If true, whenever such relationship is met, the children of these relationships will appear in a cell to the right of their parent node. If False, then for each child a new row is appended under the parent row.
graphType (string)"node"
indentation (boolean)defines if this is the indentation column. You can have only one indentation column
fields (object)
label (string)
category (string)
width (number)
relationships (array)
nodes (array)
columns (array(column))
style (array)intable cell style
css (array)header style

Field properties

ParametersExplanation

Output

For now we only support 'html' as an output.

Driver

const neo4j = require('neo4j-driver');
const cypherDriver = neo4j.driver('bolt://<neo4jBoltAddress>', neo4j.auth.basic(
  '<username>',
  '<password>',
), { disableLosslessIntegers: true, encrypted: true });

How it works

Running Cypher

An array of cypher queries is provided as an input. Each cypher query object has the following schema:

  Joi.object({
    id: Joi.string().required(),
    query: Joi.string().required(),
    ordering: Joi.array(),
    structure: Joi.array().items(Joi.object({
      identifier: Joi.string(),
      children: Joi.array().items(Joi.object({
        identifier: Joi.string(),
        children: Joi.array().items(Joi.link('#structureNodeType')),
      })),
    }).id('structureNodeType')),
  })

The queries are run by the file cypherQueries.js. They are run asynchronously. Their result is stored in a dataStore variable when all the promise resolve.

The result is obtained from the function parseQueryResult which converts the neo4j default formatting into nodes and relationships. Some cypher may return values instead of nodes/edges. In this case we also return these as key-value pair.

The returned object has the following format:

return {nodes,edges,values};

Converting to table

Once the datastore is built, the publisher scripts convert the datastore into an html table. publisher.tableConverter.js is the script converting the data into lines and columns, while publisher.js is building the table wrapper.

Process

  1. we retrieve the nodes parent-most nodes. Nodes that don't have parents are selected first.
  2. we then iterate the resulting array.
  3. for each item, we manage their inline relationships first and then fetch their non-inline relationships to build a data-tree corresponding to the structure template by running this process recursively.
  4. The data-tree is converted into the table
    1. We first manage the indentation/level columns

Code of Conduct

License

Roadmap

Evolution of features are listed on the project kanban board

Semver

Until ganister-cypher-reporter reaches a 1.0.0 release, breaking changes will be released with a new minor version.

0.0.76

1 year ago

0.0.74

1 year ago

0.0.75

1 year ago

0.0.73

1 year ago

0.0.70

1 year ago

0.0.71

1 year ago

0.0.72

1 year ago

0.0.69

1 year ago

0.0.68

2 years ago

0.0.62

2 years ago

0.0.63

2 years ago

0.0.65

2 years ago

0.0.66

2 years ago

0.0.67

2 years ago

0.0.61

2 years ago

0.0.60

2 years ago

0.0.59

2 years ago

0.0.58

2 years ago

0.0.57

3 years ago

0.0.52

3 years ago

0.0.53

3 years ago

0.0.54

3 years ago

0.0.55

3 years ago

0.0.56

3 years ago

0.0.51

3 years ago

0.0.50

3 years ago

0.0.46

3 years ago

0.0.47

3 years ago

0.0.48

3 years ago

0.0.49

3 years ago

0.0.44

3 years ago

0.0.45

3 years ago

0.0.40

3 years ago

0.0.41

3 years ago

0.0.42

3 years ago

0.0.43

3 years ago

0.0.38

3 years ago

0.0.39

3 years ago

0.0.37

3 years ago

0.0.36

3 years ago

0.0.33

3 years ago

0.0.34

3 years ago

0.0.35

3 years ago

0.0.30

3 years ago

0.0.31

3 years ago

0.0.32

3 years ago

0.0.29

3 years ago

0.0.27

3 years ago

0.0.28

3 years ago

0.0.21

3 years ago

0.0.22

3 years ago

0.0.23

3 years ago

0.0.24

3 years ago

0.0.25

3 years ago

0.0.26

3 years ago

0.0.20

3 years ago

0.0.19

3 years ago

0.0.16

3 years ago

0.0.17

3 years ago

0.0.18

3 years ago

0.0.13

3 years ago

0.0.14

3 years ago

0.0.15

3 years ago

0.0.12

3 years ago

0.0.11

3 years ago

0.0.10

3 years ago

0.0.9

3 years ago

0.0.8

3 years ago

0.0.7

3 years ago

0.0.6

3 years ago

0.0.5

3 years ago

0.0.4

3 years ago

0.0.3

3 years ago

0.0.2

3 years ago

0.0.1

3 years ago