-
Notifications
You must be signed in to change notification settings - Fork 1
17 Movies People Graph
JP Barbosa edited this page Apr 15, 2023
·
2 revisions
code ./packages/graph/src/movies/queries/_return.ts
export const _return = `
RETURN DISTINCT movie {
.*,
id: id(movie),
people: {
actors: [ (person:Person)-[r:ACTED_IN]->(movie) | person { .*, id: id(person), roles: r.roles } ],
directors: [ (person:Person)-[r:DIRECTED]->(movie) | person { .*, id: id(person) } ],
producers: [ (person:Person)-[r:PRODUCED]->(movie) | person { .*, id: id(person) } ],
writers: [ (person:Person)-[r:WROTE]->(movie) | person { .*, id: id(person) } ],
reviewers: [ (person:Person)-[r:REVIEWED]->(movie) | person { .*, id: id(person) } ]
}
}
`;
code ./packages/graph/src/movies/queries/getAll.ts
import { _return } from './_return';
export const getAll = `
WITH toLower($search) AS search
MATCH (movie:Movie)
OPTIONAL MATCH (person:Person)-[r]->(movie)
WITH *
WHERE
search IS NULL
OR search = ""
OR toLower(movie.title) CONTAINS search
OR toLower(person.name) CONTAINS search
WITH movie
${_return}
ORDER BY movie.title
`;
code ./packages/graph/src/movies/queries/getById.ts
import { _return } from './_return';
export const getById = `
MATCH (movie:Movie)
WHERE id(movie) = $id
${_return}
`;
code ./packages/graph/src/movies/queries/create.ts
import { _return } from './_return';
const createRelationships = ({
key,
collection,
}: {
key: string;
collection: string;
}) => `
WITH movie
CALL {
WITH movie
UNWIND $movie.people.${collection} AS person
MERGE (personNode:Person {
name: person.name
})
SET
personNode.born = person.born
MERGE (personNode)-[r:${key}]->(movie)
${key === 'ACTED_IN' ? 'SET r.roles = person.roles' : ''}
RETURN collect(personNode) AS ${collection}
}
`;
export const create = `
CREATE (movie:Movie)
SET
movie.title = $movie.title,
movie.released = $movie.released,
movie.tagline = $movie.tagline
WITH movie
${createRelationships({ key: 'ACTED_IN', collection: 'actors' })}
${createRelationships({ key: 'DIRECTED', collection: 'directors' })}
${createRelationships({ key: 'PRODUCED', collection: 'producers' })}
${createRelationships({ key: 'WROTE', collection: 'writers' })}
${createRelationships({ key: 'REVIEWED', collection: 'reviewers' })}
${_return}
`;
code ./packages/graph/src/movies/queries/update.ts
import { _return } from './_return';
const updateRelationships = ({
key,
collection,
}: {
key: string;
collection: string;
}) => {
return `
WITH movie
CALL {
WITH movie
UNWIND $movie.people.${collection} AS person
MERGE (personNode:Person {
name: person.name
})
SET
personNode.born = person.born
MERGE (personNode)-[r:${key}]->(movie)
${key === 'ACTED_IN' ? 'SET r.roles = person.roles' : ''}
RETURN collect(ID(r)) AS relationshipIds
}
// Delete old relationships
CALL {
WITH movie, relationshipIds
MATCH (personNode:Person)-[r:${key}]->(movie)
WHERE NOT ID(r) IN relationshipIds
DELETE r
RETURN count(r) AS deleted
}
`;
};
export const update = `
MATCH (movie:Movie)
WHERE id(movie) = $id
SET
movie.title = $movie.title,
movie.released = $movie.released,
movie.tagline = $movie.tagline
${updateRelationships({ key: 'ACTED_IN', collection: 'actors' })}
${updateRelationships({ key: 'DIRECTED', collection: 'directors' })}
${updateRelationships({ key: 'PRODUCED', collection: 'producers' })}
${updateRelationships({ key: 'WROTE', collection: 'writers' })}
${updateRelationships({ key: 'REVIEWED', collection: 'reviewers' })}
${_return}
`;
code ./packages/graph/src/movies/index.spec.ts
...
export const expectMoviesToBeEqual = (movie1: Movie, movie2: Movie) => {
...
Object.keys(movie1Parsed.people).forEach((key) => {
expect(movie1Parsed.people[key]).toIncludeSameMembers(
movie2Parsed.people[key]
);
});
};
describe('graph.movies', () => {
...
it('should create a movie', ...);
it('should get the previously created movie', ...);
it('should update movie tagline', ...);
it('should add one actor and one reviewer to the movie', async () => {
const [movie] = await graph.movies(session).getAll(sampleMovie.title);
movie.people.actors.push({
name: 'Clancy Brown',
born: 1959,
roles: ['Captain Andrew Ryan'],
});
const updatedMovie = await graph.movies(session).update(movie.id, movie);
expectMoviesToBeEqual(updatedMovie, movie);
});
it('should remove one actor and one reviewer from the movie', async () => {
const [movie] = await graph.movies(session).getAll(sampleMovie.title);
movie.people.actors.pop();
movie.people.reviewers.pop();
const updatedMovie = await graph.movies(session).update(movie.id, movie);
expectMoviesToBeEqual(updatedMovie, movie);
});
it('should delete the movie', ...);
});
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: 10 passed, 10 total
Snapshots: 0 total
Time: 4.252 s
Ran all test suites.
git add .
git commit -m "Movies People Graph"