diff --git a/.gitignore b/.gitignore index 70cf5c32..848d400b 100644 --- a/.gitignore +++ b/.gitignore @@ -69,4 +69,10 @@ neo4j-version test/tck/* !test/tck/.gitkeep -.history \ No newline at end of file +.history + +__MACOSX +neo4j + +neo4j-enterprise* +recommendations.db.zip* \ No newline at end of file diff --git a/example/apollo-server/authScopes.js b/example/apollo-server/authScopes.js index 4f1d244b..ccd83dff 100644 --- a/example/apollo-server/authScopes.js +++ b/example/apollo-server/authScopes.js @@ -1,3 +1,4 @@ +import { gql } from 'apollo-server'; import { makeAugmentedSchema } from '../../src/index'; import { ApolloServer } from 'apollo-server'; import neo4j from 'neo4j-driver'; @@ -11,15 +12,15 @@ import neo4j from 'neo4j-driver'; // JWT_SECRET // oqldBPU1yMXcrTwcha1a9PGi9RHlPVzQ -const typeDefs = ` -type User { +const typeDefs = gql` + type User { userId: ID! name: String -} + } -type Business { + type Business { name: String -} + } `; const schema = makeAugmentedSchema({ diff --git a/example/apollo-server/bookmarks.js b/example/apollo-server/bookmarks.js index 5dbba301..326e9c95 100644 --- a/example/apollo-server/bookmarks.js +++ b/example/apollo-server/bookmarks.js @@ -1,47 +1,47 @@ +import { gql } from 'apollo-server'; import { makeAugmentedSchema } from '../../src/index'; import { ApolloServer } from 'apollo-server'; import neo4j from 'neo4j-driver'; -const typeDefs = ` -type Person { - _id: Long! - born: Int - name: String! - acted_in: [Movie] @relation(name: "ACTED_IN", direction: "OUT") - ACTED_IN_rel: [ACTED_IN] - directed: [Movie] @relation(name: "DIRECTED", direction: "OUT") - produced: [Movie] @relation(name: "PRODUCED", direction: "OUT") - wrote: [Movie] @relation(name: "WROTE", direction: "OUT") - follows: [Person] @relation(name: "FOLLOWS", direction: "OUT") - reviewed: [Movie] @relation(name: "REVIEWED", direction: "OUT") - REVIEWED_rel: [REVIEWED] -} - -type Movie { - _id: Long! - released: Int! - tagline: String - title: String! - persons_acted_in: [Person] @relation(name: "ACTED_IN", direction: "IN") - persons_directed: [Person] @relation(name: "DIRECTED", direction: "IN") - persons_produced: [Person] @relation(name: "PRODUCED", direction: "IN") - persons_wrote: [Person] @relation(name: "WROTE", direction: "IN") - persons_reviewed: [Person] @relation(name: "REVIEWED", direction: "IN") -} +const typeDefs = gql` + type Person { + _id: Long! + born: Int + name: String! + acted_in: [Movie] @relation(name: "ACTED_IN", direction: "OUT") + ACTED_IN_rel: [ACTED_IN] + directed: [Movie] @relation(name: "DIRECTED", direction: "OUT") + produced: [Movie] @relation(name: "PRODUCED", direction: "OUT") + wrote: [Movie] @relation(name: "WROTE", direction: "OUT") + follows: [Person] @relation(name: "FOLLOWS", direction: "OUT") + reviewed: [Movie] @relation(name: "REVIEWED", direction: "OUT") + REVIEWED_rel: [REVIEWED] + } -type ACTED_IN @relation(name: "ACTED_IN") { - from: Person! - to: Movie! - roles: [String]! -} + type Movie { + _id: Long! + released: Int! + tagline: String + title: String! + persons_acted_in: [Person] @relation(name: "ACTED_IN", direction: "IN") + persons_directed: [Person] @relation(name: "DIRECTED", direction: "IN") + persons_produced: [Person] @relation(name: "PRODUCED", direction: "IN") + persons_wrote: [Person] @relation(name: "WROTE", direction: "IN") + persons_reviewed: [Person] @relation(name: "REVIEWED", direction: "IN") + } -type REVIEWED @relation(name: "REVIEWED") { - from: Person! - to: Movie! - rating: Int! - summary: String! -} + type ACTED_IN @relation(name: "ACTED_IN") { + from: Person! + to: Movie! + roles: [String]! + } + type REVIEWED @relation(name: "REVIEWED") { + from: Person! + to: Movie! + rating: Int! + summary: String! + } `; const schema = makeAugmentedSchema({ typeDefs }); diff --git a/example/apollo-server/interface-union-example.js b/example/apollo-server/interface-union-example.js index 09780ff0..6f589ec7 100644 --- a/example/apollo-server/interface-union-example.js +++ b/example/apollo-server/interface-union-example.js @@ -1,24 +1,28 @@ +import { gql } from 'apollo-server'; import { makeAugmentedSchema } from '../../src/index'; const { ApolloServer } = require('apollo-server'); const neo4j = require('neo4j-driver'); -const __unionTypeDefs = ` -union SearchResult = Blog | Movie +const __unionTypeDefs = gql` + union SearchResult = Blog | Movie -type Blog { - blogId: ID! - created: DateTime - content: String -} + type Blog { + blogId: ID! + created: DateTime + content: String + } -type Movie { - movieId: ID! - title: String -} + type Movie { + movieId: ID! + title: String + } -type Query { - search(searchString: String!): [SearchResult] @cypher(statement:"CALL db.index.fulltext.queryNodes('searchIndex', $searchString) YIELD node RETURN node") -} + type Query { + search(searchString: String!): [SearchResult] + @cypher( + statement: "CALL db.index.fulltext.queryNodes('searchIndex', $searchString) YIELD node RETURN node" + ) + } `; const __interfaceTypeDefs = ` diff --git a/example/apollo-server/movies-schema.js b/example/apollo-server/movies-schema.js index 5c4a5814..de82c05b 100644 --- a/example/apollo-server/movies-schema.js +++ b/example/apollo-server/movies-schema.js @@ -1,143 +1,176 @@ +import { gql } from 'apollo-server'; import { neo4jgraphql } from '../../src/index'; -export const typeDefs = ` -type Movie { - movieId: ID! - title: String - someprefix_title_with_underscores: String - year: Int - dateTime: DateTime - localDateTime: LocalDateTime - date: Date - plot: String - poster: String - imdbRating: Float - ratings: [Rated] - genres: [Genre] @relation(name: "IN_GENRE", direction: "OUT") - similar(first: Int = 3, offset: Int = 0, limit: Int = 5): [Movie] @cypher(statement: "MATCH (this)--(:Genre)--(o:Movie) RETURN o LIMIT $limit") - mostSimilar: Movie @cypher(statement: "RETURN this") - degree: Int @cypher(statement: "RETURN SIZE((this)--())") - actors(first: Int = 3, offset: Int = 0): [Actor] @relation(name: "ACTED_IN", direction:"IN") - avgStars: Float - filmedIn: State @relation(name: "FILMED_IN", direction: "OUT") - location: Point - locations: [Point] - scaleRating(scale: Int = 3): Float @cypher(statement: "RETURN $scale * this.imdbRating") - scaleRatingFloat(scale: Float = 1.5): Float @cypher(statement: "RETURN $scale * this.imdbRating") - _id: ID -} - -type Genre { - name: String - movies(first: Int = 3, offset: Int = 0): [Movie] @relation(name: "IN_GENRE", direction: "IN") - highestRatedMovie: Movie @cypher(statement: "MATCH (m:Movie)-[:IN_GENRE]->(this) RETURN m ORDER BY m.imdbRating DESC LIMIT 1") -} - -type State { - name: String -} - -interface Person { - userId: ID! - name: String -} - -type Actor { - id: ID! - name: String - movies: [Movie] @relation(name: "ACTED_IN", direction: "OUT") - knows: [Person] @relation(name: "KNOWS", direction: "OUT") -} - -type User implements Person { - userId: ID! - name: String - rated: [Rated] -} - -type Rated @relation(name:"RATED") { - from: User - to: Movie - timestamp: Int - date: Date - rating: Float -} -enum BookGenre { - Mystery, - Science, - Math -} - -type OnlyDate { - date: Date -} - -type SpatialNode { - id: ID! - point: Point - spatialNodes(point: Point): [SpatialNode] - @relation(name: "SPATIAL", direction: OUT) -} - -type Book { - genre: BookGenre -} - -interface Camera { - id: ID! - type: String - make: String - weight: Int - operators: [Person] @relation(name: "cameras", direction: IN) - computedOperators(name: String): [Person] @cypher(statement: "MATCH (this)<-[:cameras]-(p:Person) RETURN p") -} - -type OldCamera implements Camera { - id: ID! - type: String - make: String - weight: Int - smell: String - operators: [Person] @relation(name: "cameras", direction: IN) - computedOperators(name: String): [Person] @cypher(statement: "MATCH (this)<-[:cameras]-(p:Person) RETURN p") -} - -type NewCamera implements Camera { - id: ID! - type: String - make: String - weight: Int - features: [String] - operators: [Person] @relation(name: "cameras", direction: IN) - computedOperators(name: String): [Person] @cypher(statement: "MATCH (this)<-[:cameras]-(p:Person) RETURN p") -} - -type CameraMan implements Person { - userId: ID! - name: String - favoriteCamera: Camera @relation(name: "favoriteCamera", direction: "OUT") - heaviestCamera: [Camera] @cypher(statement: "MATCH (c: Camera)--(this) RETURN c ORDER BY c.weight DESC LIMIT 1") - cameras: [Camera!]! @relation(name: "cameras", direction: "OUT") - cameraBuddy: Person @relation(name: "cameraBuddy", direction: "OUT") -} - -union MovieSearch = Movie | Genre | Book | User | OldCamera - -type Query { - Movie(movieId: ID, title: String, year: Int, plot: String, poster: String, imdbRating: Float): [Movie] - MoviesByYear(year: Int, first: Int = 10, offset: Int = 0): [Movie] - AllMovies: [Movie] - MovieById(movieId: ID!): Movie - GenresBySubstring(substring: String): [Genre] @cypher(statement: "MATCH (g:Genre) WHERE toLower(g.name) CONTAINS toLower($substring) RETURN g") - Books: [Book] - CustomCameras: [Camera] @cypher(statement: "MATCH (c:Camera) RETURN c") - CustomCamera: Camera @cypher(statement: "MATCH (c:Camera) RETURN c") -} - -type Mutation { - CustomCamera: Camera @cypher(statement: "CREATE (newCamera:Camera:NewCamera {id: apoc.create.uuid(), type: 'macro'}) RETURN newCamera") - CustomCameras: [Camera] @cypher(statement: "CREATE (newCamera:Camera:NewCamera {id: apoc.create.uuid(), type: 'macro', features: ['selfie', 'zoom']}) CREATE (oldCamera:Camera:OldCamera {id: apoc.create.uuid(), type: 'floating', smell: 'rusty' }) RETURN [newCamera, oldCamera]") -} +export const typeDefs = gql` + type Movie { + movieId: ID! + title: String + someprefix_title_with_underscores: String + year: Int + dateTime: DateTime + localDateTime: LocalDateTime + date: Date + plot: String + poster: String + imdbRating: Float + ratings: [Rated] + genres: [Genre] @relation(name: "IN_GENRE", direction: "OUT") + similar(first: Int = 3, offset: Int = 0, limit: Int = 5): [Movie] + @cypher( + statement: "MATCH (this)--(:Genre)--(o:Movie) RETURN o LIMIT $limit" + ) + mostSimilar: Movie @cypher(statement: "RETURN this") + degree: Int @cypher(statement: "RETURN SIZE((this)--())") + actors(first: Int = 3, offset: Int = 0): [Actor] + @relation(name: "ACTED_IN", direction: "IN") + avgStars: Float + filmedIn: State @relation(name: "FILMED_IN", direction: "OUT") + location: Point + locations: [Point] + scaleRating(scale: Int = 3): Float + @cypher(statement: "RETURN $scale * this.imdbRating") + scaleRatingFloat(scale: Float = 1.5): Float + @cypher(statement: "RETURN $scale * this.imdbRating") + _id: ID + } + + type Genre { + name: String + movies(first: Int = 3, offset: Int = 0): [Movie] + @relation(name: "IN_GENRE", direction: "IN") + highestRatedMovie: Movie + @cypher( + statement: "MATCH (m:Movie)-[:IN_GENRE]->(this) RETURN m ORDER BY m.imdbRating DESC LIMIT 1" + ) + } + + type State { + name: String + } + + interface Person { + userId: ID! + name: String + } + + type Actor { + id: ID! + name: String + movies: [Movie] @relation(name: "ACTED_IN", direction: "OUT") + knows: [Person] @relation(name: "KNOWS", direction: "OUT") + } + + type User implements Person { + userId: ID! + name: String + rated: [Rated] + } + + type Rated @relation(name: "RATED") { + from: User + to: Movie + timestamp: Int + date: Date + rating: Float + } + enum BookGenre { + Mystery + Science + Math + } + + type OnlyDate { + date: Date + } + + type SpatialNode { + id: ID! + point: Point + spatialNodes(point: Point): [SpatialNode] + @relation(name: "SPATIAL", direction: OUT) + } + + type Book { + genre: BookGenre + } + + interface Camera { + id: ID! + type: String + make: String + weight: Int + operators: [Person] @relation(name: "cameras", direction: IN) + computedOperators(name: String): [Person] + @cypher(statement: "MATCH (this)<-[:cameras]-(p:Person) RETURN p") + } + + type OldCamera implements Camera { + id: ID! + type: String + make: String + weight: Int + smell: String + operators: [Person] @relation(name: "cameras", direction: IN) + computedOperators(name: String): [Person] + @cypher(statement: "MATCH (this)<-[:cameras]-(p:Person) RETURN p") + } + + type NewCamera implements Camera { + id: ID! + type: String + make: String + weight: Int + features: [String] + operators: [Person] @relation(name: "cameras", direction: IN) + computedOperators(name: String): [Person] + @cypher(statement: "MATCH (this)<-[:cameras]-(p:Person) RETURN p") + } + + type CameraMan implements Person { + userId: ID! + name: String + favoriteCamera: Camera @relation(name: "favoriteCamera", direction: "OUT") + heaviestCamera: [Camera] + @cypher( + statement: "MATCH (c: Camera)--(this) RETURN c ORDER BY c.weight DESC LIMIT 1" + ) + cameras: [Camera!]! @relation(name: "cameras", direction: "OUT") + cameraBuddy: Person @relation(name: "cameraBuddy", direction: "OUT") + } + + union MovieSearch = Movie | Genre | Book | User | OldCamera + + type Query { + Movie( + movieId: ID + title: String + year: Int + plot: String + poster: String + imdbRating: Float + ): [Movie] + MoviesByYear(year: Int, first: Int = 10, offset: Int = 0): [Movie] + AllMovies: [Movie] + MovieById(movieId: ID!): Movie + GenresBySubstring(substring: String): [Genre] + @cypher( + statement: "MATCH (g:Genre) WHERE toLower(g.name) CONTAINS toLower($substring) RETURN g" + ) + Books: [Book] + CustomCameras: [Camera] @cypher(statement: "MATCH (c:Camera) RETURN c") + CustomCamera: Camera @cypher(statement: "MATCH (c:Camera) RETURN c") + } + + type Mutation { + CustomCamera: Camera + @cypher( + statement: "CREATE (newCamera:Camera:NewCamera {id: apoc.create.uuid(), type: 'macro'}) RETURN newCamera" + ) + CustomCameras: [Camera] + @cypher( + statement: "CREATE (newCamera:Camera:NewCamera {id: apoc.create.uuid(), type: 'macro', features: ['selfie', 'zoom']}) CREATE (oldCamera:Camera:OldCamera {id: apoc.create.uuid(), type: 'floating', smell: 'rusty' }) RETURN [newCamera, oldCamera]" + ) + } `; export const resolvers = { diff --git a/example/apollo-server/movies-typedefs.js b/example/apollo-server/movies-typedefs.js index aac3d43f..cf77d405 100644 --- a/example/apollo-server/movies-typedefs.js +++ b/example/apollo-server/movies-typedefs.js @@ -1,47 +1,48 @@ +import { gql } from 'apollo-server'; import { makeAugmentedSchema } from '../../src/index'; import { ApolloServer } from 'apollo-server'; import { v1 as neo4j } from 'neo4j-driver'; -const typeDefs = ` -type Movie { - movieId: ID! - title: String - year: Int - plot: String - poster: String - imdbRating: Float - ratings: [Rated] - genres: [Genre] @relation(name: "IN_GENRE", direction: "OUT") - actors: [Actor] @relation(name: "ACTED_IN", direction: "IN") -} -type Genre { - name: String - movies: [Movie] @relation(name: "IN_GENRE", direction: "IN") -} -type Actor { - id: ID! - name: String - movies: [Movie] @relation(name: "ACTED_IN", direction: "OUT") -} -type User { - userId: ID! - name: String - rated: [Rated] - recommendedMovies: [Movie] - @cypher( - statement: """ - MATCH (this)-[:RATED]->(:Movie)<-[:RATED]-(:User)-[:RATED]->(rec:Movie) - WITH rec, COUNT(*) AS score ORDER BY score DESC LIMIT 10 - RETURN rec - """ - ) -} -type Rated @relation(name: "RATED") { - from: User - to: Movie - rating: Float - created: DateTime -} +const typeDefs = gql` + type Movie { + movieId: ID! + title: String + year: Int + plot: String + poster: String + imdbRating: Float + ratings: [Rated] + genres: [Genre] @relation(name: "IN_GENRE", direction: "OUT") + actors: [Actor] @relation(name: "ACTED_IN", direction: "IN") + } + type Genre { + name: String + movies: [Movie] @relation(name: "IN_GENRE", direction: "IN") + } + type Actor { + id: ID! + name: String + movies: [Movie] @relation(name: "ACTED_IN", direction: "OUT") + } + type User { + userId: ID! + name: String + rated: [Rated] + recommendedMovies: [Movie] + @cypher( + statement: """ + MATCH (this)-[:RATED]->(:Movie)<-[:RATED]-(:User)-[:RATED]->(rec:Movie) + WITH rec, COUNT(*) AS score ORDER BY score DESC LIMIT 10 + RETURN rec + """ + ) + } + type Rated @relation(name: "RATED") { + from: User + to: Movie + rating: Float + created: DateTime + } `; const schema = makeAugmentedSchema({ typeDefs }); diff --git a/example/apollo-server/multidatabase.js b/example/apollo-server/multidatabase.js index 5ff6e374..16e19d6c 100644 --- a/example/apollo-server/multidatabase.js +++ b/example/apollo-server/multidatabase.js @@ -1,10 +1,10 @@ +import { gql } from 'apollo-server'; import { makeAugmentedSchema } from '../../src/index'; import { ApolloServer } from 'apollo-server'; import neo4j from 'neo4j-driver'; -const typeDefs = ` - -type User { +const typeDefs = gql` + type User { name: String! wrote: [Review] @relation(name: "WROTE", direction: "OUT") } diff --git a/scripts/install-neo4j.sh b/scripts/install-neo4j.sh old mode 100755 new mode 100644 index e58ea6b8..b22c358e --- a/scripts/install-neo4j.sh +++ b/scripts/install-neo4j.sh @@ -1,5 +1,10 @@ #!/usr/bin/env bash +if [ ! -f ../.env ] +then + export $(cat .env | xargs) +fi + set -xe if [ ! -d "neo4j/data/databases/graph.db" ]; then