Skip to content

19 Visualization Graph And API

JP Barbosa edited this page Apr 15, 2023 · 2 revisions

Visualization Graph and API

Install Required Packages

npm install vis-network

Shared Types

code ./packages/shared/src/types/GraphVisData.ts
import { Node, Edge } from 'vis-network/standalone';

export interface GraphVisData {
  nodes: Node[];
  edges: Edge[];
}
code ./packages/shared/src/types/index.ts
export * from './GraphVisData';

Graph

code ./packages/graph/src/visualization/queries/get.ts
export const get = `
  WITH toLower($search) AS search
  MATCH (person:Person)-[r]->(movie:Movie)
  WHERE
    search IS NULL
    OR search = ""
    OR toLower(movie.title) CONTAINS search
    OR toLower(person.name) CONTAINS search
  RETURN *
`;
code ./packages/graph/src/visualization/queries/index.ts
export * from './get';
code ./packages/graph/src/visualization/index.ts
import { Relationship, Session } from 'neo4j-driver';
import { Node, Edge } from 'vis-network/standalone';
import { GraphVisData, MovieNode, PersonNode } from '@neo4j-crud/shared';
import * as queries from './queries';

type GetGraphReturn = GraphVisData;

type GetGraphResults = {
  person: PersonNode;
  movie: MovieNode;
  r: Relationship;
};

export const visualization = (session: Session) => ({
  get: async (search = ''): Promise<GetGraphReturn> => {
    const result = await session.run<GetGraphResults>(queries.get, { search });

    const nodes: Node[] = [];
    const edges: Edge[] = [];

    result.records.forEach((record) => {
      const movie = record.get('movie');
      const person = record.get('person');
      const edge = record.get('r');

      if (!nodes.find((node) => node.id === movie.identity.toString())) {
        nodes.push({
          label: movie.properties.title,
          id: movie.identity.toString(),
          group: 'Movie',
        });
      }

      if (!nodes.find((node) => node.id === person.identity.toString())) {
        nodes.push({
          label: person.properties.name,
          id: person.identity.toString(),
          group: 'Person',
        });
      }

      if (edge) {
        edges.push({
          label: edge.type,
          id: edge.identity.toString(),
          from: edge.start.toString(),
          to: edge.end.toString(),
        });
      }
    });

    return {
      nodes,
      edges,
    };
  },
});
code ./packages/graph/src/index.ts
...
export * from './visualization';

API

code ./packages/api/src/controllers/visualization.ts
import { NextFunction } from 'express';
import { AppResponse, GraphVisData } from '@neo4j-crud/shared';
import * as graph from '@neo4j-crud/graph';

export const visualizationController = {
  get: async (req, res: AppResponse<GraphVisData>, next: NextFunction) => {
    try {
      const search = req.query.search as string;
      const result = await graph.visualization(req.neo4jSession).get(search);
      res.send(result);
    } catch (err) {
      next(err);
    }
  },
};
code ./packages/api/src/controllers/index.ts
...
export * from './visualization';
code ./packages/api/src/routes/visualization.ts
import { Router } from 'express';
import { visualizationController } from '../controllers';

const router = Router();

router.get('/', visualizationController.get);

export default router;
code ./packages/api/src/routes/index.ts
...
import visualizationRouter from './visualization';

...

routers.use('/visualization', visualizationRouter);

export default routers;

Test

open "http://localhost:3333/visualization?search=Top%20Gun"
{
  "nodes": [
    {
      "label": "Top Gun",
      "id": "1",
      "group": "Movie"
    },
    {
      "label": "Tony Scott",
      "id": "2",
      "group": "Person"
    },
    ...
  ],
  "edges": [
    {
      "label": "DIRECTED",
      "id": "3",
      "from": "2",
      "to": "1"
    },
    ...
  ]
}

Commit

git add .
git commit -m "Visualization Graph And API"