13 People Graph - jpbarbosa/neo4j-crud GitHub Wiki

People Graph

Default Return

code ./packages/graph/src/people/queries/_return.ts
export const _return = `
  RETURN DISTINCT person {
    .*,
    id: id(person),
    movies: [ (person)-[r]->(movie:Movie) | movie { .*, id: id(movie), relationship: type(r) } ]
  }
`;

Get All

code ./packages/graph/src/people/queries/getAll.ts
import { _return } from './_return';

export const getAll = `
  WITH toLower($search) AS search
  MATCH (person:Person)
  OPTIONAL MATCH (person)-[r]->(movie:Movie)
  WITH *
  WHERE
    search IS NULL
    OR search = ""
    OR toLower(movie.title) CONTAINS search
    OR toLower(person.name) CONTAINS search
  WITH person
  ${_return}
  ORDER BY person.name
`;

Get By ID

code ./packages/graph/src/people/queries/getById.ts
import { _return } from './_return';

export const getById = `
  MATCH (person:Person)
  WHERE id(person) = $id
  ${_return}
`;

Create

code ./packages/graph/src/people/queries/create.ts
import { _return } from './_return';

export const create = `
  CREATE (person:Person)
  SET
    person.name = $person.name,
    person.born = $person.born

  ${_return}
`;

Update

code ./packages/graph/src/people/queries/update.ts
import { _return } from './_return';

export const update = `
  MATCH (person:Person)
  WHERE id(person) = $id
  SET
    person.name = $person.name,
    person.born = $person.born

  ${_return}
`;

Remove

code ./packages/graph/src/people/queries/remove.ts
export const remove = `
  MATCH (person:Person)
  WHERE id(person) = $id
  DETACH DELETE person
`;

Index

code ./packages/graph/src/people/queries/index.ts
export * from './getAll';
export * from './getById';
export * from './create';
export * from './update';
export * from './remove';

Methods

code ./packages/graph/src/people/index.ts
import { Session } from 'neo4j-driver';
import { PeopleQueryResult, Person } from '@neo4j-crud/shared';
import * as queries from './queries';

export const people = (session: Session) => ({
  getAll: async (search = '') => {
    const result = await session.run<PeopleQueryResult>(queries.getAll, {
      search,
    });

    const records = result.records.map((record) => record.get('person'));

    return records;
  },

  getById: async (id: number) => {
    const result = await session.run<PeopleQueryResult>(queries.getById, {
      id,
    });

    const records = result.records.map((record) => record.get('person'));

    return records.pop();
  },

  update: async (id: number, person: Person) => {
    const result = await session.run<PeopleQueryResult>(queries.update, {
      id,
      person,
    });

    const records = result.records.map((record) => record.get('person'));

    return records.pop();
  },

  create: async (person: Person) => {
    const result = await session.run<PeopleQueryResult>(queries.create, {
      person,
    });

    const records = result.records.map((record) => record.get('person'));

    return records.pop();
  },

  remove: async (id: number) => {
    const result = await session.run<PeopleQueryResult>(queries.remove, {
      id,
    });

    const records = result.records.map((record) => record.get('person'));

    return records.pop();
  },
});
code ./packages/graph/src/index.ts
...
export * from './people';

Test

code ./packages/graph/src/people/index.spec.ts
import { Driver, Session } from 'neo4j-driver';
import { Person, people as samplePeople } from '@neo4j-crud/shared';
import * as graph from './';
import { neo4jDriver } from '../utils/neo4jDriver';
import {
  neo4jConfigFile,
  Neo4jContainerConfig,
} from '../utils/neo4jConfigFile';
import { ignoreId } from '../utils/ignoreId';

export const expectPeopleToBeEqual = (person1: Person, person2: Person) => {
  const person1Parsed = ignoreId(person1);
  const person2Parsed = ignoreId(person2);

  expect(person1Parsed.name).toEqual(person2Parsed.name);
  expect(person1Parsed.born).toEqual(person2Parsed.born);
};

describe('graph.people', () => {
  jest.setTimeout(180_000);

  let neo4jConfig: Neo4jContainerConfig;
  let driver: Driver;
  let session: Session;
  const samplePerson = samplePeople[0];

  const clearDatabase = async () => {
    await session.run('MATCH (n) DETACH DELETE n');
  };

  beforeAll(async () => {
    neo4jConfig = await neo4jConfigFile().read();
    driver = await neo4jDriver(neo4jConfig);
    session = driver.session();
    await clearDatabase();
  });

  afterAll(async () => {
    await session.close();
    await driver.close();
    //await container.stop();
  });

  it('should create a person', async () => {
    const person = await graph.people(session).create(samplePerson);
    expectPeopleToBeEqual(person, samplePerson);
  });

  it('should get the previously created person', async () => {
    const [person] = await graph.people(session).getAll(samplePerson.name);
    expectPeopleToBeEqual(person, samplePerson);
  });

  it('should update person tagline', async () => {
    const [person] = await graph.people(session).getAll(samplePerson.name);
    person.name += ' updated';
    const updatedPerson = await graph.people(session).update(person.id, person);
    expectPeopleToBeEqual(updatedPerson, person);
  });

  it('should delete the person', async () => {
    const [person] = await graph.people(session).getAll(samplePerson.name);
    await graph.people(session).remove(person.id);
    const people = await graph.people(session).getAll(samplePerson.name);
    expect(people).toHaveLength(0);
  });
});
nx test graph
Determining test suites to run...
Neo4j container found at localhost:32768
 PASS   graph  packages/graph/src/people/index.spec.ts
 PASS   graph  packages/graph/src/movies/index.spec.ts

Test Suites: 2 passed, 2 total
Tests:       8 passed, 8 total
Snapshots:   0 total
Time:        2.892 s, estimated 3 s
Ran all test suites.

Commit

git add .
git commit -m "People Graph"

Next step: People API