All Projects → Usama0121 → neo4j-graphql-py

Usama0121 / neo4j-graphql-py

Licence: other
A GraphQL to Cypher query execution layer for Neo4j and Python GraphQL implementations.

Programming Languages

python
139335 projects - #7 most used programming language

Projects that are alternatives of or similar to neo4j-graphql-py

neo4rs
Neo4j driver for rust
Stars: ✭ 41 (+192.86%)
Mutual labels:  neo4j, neo4j-database, neo4j-driver
py2neo
Py2neo is a comprehensive Neo4j driver library and toolkit for Python.
Stars: ✭ 1,105 (+7792.86%)
Mutual labels:  neo4j, neo4j-database, neo4j-driver
seabolt
Neo4j Bolt Connector for C
Stars: ✭ 37 (+164.29%)
Mutual labels:  neo4j, neo4j-database, neo4j-driver
neo listens
Sample Event Listener / Triggers
Stars: ✭ 16 (+14.29%)
Mutual labels:  neo4j, neo4j-database, neo4j-server
finch-graphql
Local GraphQL API in the background process of a web extension.
Stars: ✭ 48 (+242.86%)
Mutual labels:  graphql-server, graphql-api
kanji
A strongly typed GraphQL API framework
Stars: ✭ 12 (-14.29%)
Mutual labels:  graphql-server, graphql-api
neo4j-rake tasks
Rake tasks for managing Neo4j. Tasks allow for starting, stopping, and configuring
Stars: ✭ 13 (-7.14%)
Mutual labels:  neo4j, neo4j-server
graphql-express-nodejs
A Simple GraphQL Server implementation using Express and Node. See post here: https://t.co/Cm6GitZaBL
Stars: ✭ 24 (+71.43%)
Mutual labels:  graphql-server, graphql-api
angular-neo4j
Neo4j Bolt driver wrapper for Angular
Stars: ✭ 18 (+28.57%)
Mutual labels:  neo4j, neo4j-driver
OGMNeo
[No Maintenance] Neo4j nodeJS OGM(object-graph mapping) abstraction layer
Stars: ✭ 54 (+285.71%)
Mutual labels:  neo4j, neo4j-driver
graphql-example
Intuitive GraphQL Resolver Example - Application example using RawModel.js as GraphQL rootValue on steroids.
Stars: ✭ 25 (+78.57%)
Mutual labels:  graphql-query, graphql-server
Gitzilla
A resume builder for your GitHub profile.
Stars: ✭ 60 (+328.57%)
Mutual labels:  graphql-server, graphql-api
neo4j-jdbc
JDBC driver for Neo4j
Stars: ✭ 110 (+685.71%)
Mutual labels:  neo4j, neo4j-driver
neo4j-java-driver-spring-boot-starter
Automatic configuration of Neo4j's Java Driver for Spring Boot applications
Stars: ✭ 33 (+135.71%)
Mutual labels:  neo4j, neo4j-driver
ngraphql
GraphQL .NET Server and Client
Stars: ✭ 26 (+85.71%)
Mutual labels:  graphql-server, graphql-api
server
Core server in the Alkemio platform, offering a GraphQL api for interacting with the logical domain model.
Stars: ✭ 20 (+42.86%)
Mutual labels:  graphql-server, graphql-api
elixir ravelry
Elixir API using Neo4j database for ElixirConf 2017 talk
Stars: ✭ 21 (+50%)
Mutual labels:  neo4j, neo4j-database
DotNetGraphQL
A sample demonstrating how to create a GraphQL Backend in .NET and consume it from a .NET mobile app created using Xamarin
Stars: ✭ 78 (+457.14%)
Mutual labels:  graphql-server, graphql-api
graphql-api
GraphQL-Api is an opinionated Graphql framework for Rails that supports auto generating queries based on Active Record models and plain Ruby objects
Stars: ✭ 58 (+314.29%)
Mutual labels:  graphql-query, graphql-api
neo4j.cr
Pure-Crystal implementation of Neo4j's Bolt protocol
Stars: ✭ 29 (+107.14%)
Mutual labels:  neo4j, neo4j-driver

neo4j-graphql-py

A GraphQL to Cypher query execution layer for Neo4j and Python GraphQL implementations.

Installation and usage

Install

pip install neo4j-graphql-py

Then call neo4j_graphql() in your GraphQL resolver. Your GraphQL query will be translated to Cypher and the query passed to Neo4j.

from neo4j_graphql_py import neo4j_graphql

def resolve(obj, info, **kwargs):
    return neo4j_graphql(obj, info.context, info, **kwargs)

resolvers = {
  'Query': {
    'Movie':resolve
  }
}

What is neo4j-graphql-py

A package to make it easier to use GraphQL and Neo4j together. neo4j-graphql-py translates GraphQL queries to a single Cypher query, eliminating the need to write queries in GraphQL resolvers and for batching queries. It also exposes the Cypher query language through GraphQL via the @cypher schema directive.

How it works

Start with a GraphQL schema

GraphQL First Development is all about starting with a well defined GraphQL schema. Here we'll use the GraphQL schema IDL syntax:

type_defs = '''
directive @cypher(statement: String!) on FIELD_DEFINITION
directive @relation(name:String!, direction:String!) on FIELD_DEFINITION

type Movie {
  movieId: ID!
  title: String
  year: Int
  plot: String
  poster: String
  imdbRating: Float
  similar(first: Int = 3, offset: Int = 0): [Movie] @cypher(statement: "MATCH (this)-[:IN_GENRE]->(:Genre)<-[:IN_GENRE]-(o:Movie) RETURN o")
  degree: Int @cypher(statement: "RETURN SIZE((this)-->())")
  actors(first: Int = 3, offset: Int = 0): [Actor] @relation(name: "ACTED_IN", direction:"IN")
}

type Actor {
  id: ID!
  name: String
  movies: [Movie]
}


type Query {
  Movie(id: ID, title: String, year: Int, imdbRating: Float, first: Int, offset: Int): [Movie]
}
'''

We define two types, Movie and Actor as well as a top level Query Movie which becomes our entry point. This looks like a standard GraphQL schema, except for the use of two directives @relation and @cypher. In GraphQL directives allow us to annotate fields and provide an extension point for GraphQL.

  • @cypher directive - maps the specified Cypher query to the value of the field. In the Cypher query, this is bound to the current object being resolved.
  • @relation directive - used to indicate relationships in the data model. The name argument specifies the relationship type, and direction indicates the direction of the relationship ("IN" or "OUT" are valid values)

Translate GraphQL To Cypher

Inside each resolver, use neo4j-graphql() to generate the Cypher required to resolve the GraphQL query, passing through the query arguments, context and resolveInfo objects.

from neo4j_graphql_py import neo4j_graphql

resolvers = {
  # entry point to GraphQL service
  'Query': {
    'Movie': lambda obj, info, **kwargs: neo4j_graphql(obj, info.context,info, **kwargs)
  }
}

GraphQL to Cypher translation works by inspecting the GraphQL schema, the GraphQL query and arguments. For example, this simple GraphQL query

{
  Movie(title: "River Runs Through It, A") {
    title
    year
    imdbRating
  }
}

is translated into the Cypher query

MATCH (movie:Movie {title: "River Runs Through It, A"})
RETURN movie { .title , .year , .imdbRating } AS movie
SKIP 0

A slightly more complicated traversal

{
  Movie(title: "River Runs Through It, A") {
    title
    year
    imdbRating
    actors {
      name
    }
  }
}

becomes

MATCH (movie:Movie {title: "River Runs Through It, A"})
RETURN movie { .title , .year , .imdbRating, actors: [(movie)<-[:ACTED_IN]-(movie_actors:Actor) | movie_actors { .name }] }
AS movie
SKIP 0

@cypher directive

NOTE: The @cypher directive has a dependency on the APOC procedure library, specifically the function apoc.cypher.runFirstColumn to run sub-queries. If you'd like to make use of the @cypher feature you'll need to install appropriate version of APOC in Neo4j

GraphQL is fairly limited when it comes to expressing complex queries such as filtering, or aggregations. We expose the graph querying language Cypher through GraphQL via the @cypher directive. Annotate a field in your schema with the @cypher directive to map the results of that query to the annotated GraphQL field. For example:

type Movie {
  movieId: ID!
  title: String
  year: Int
  plot: String
  similar(first: Int = 3, offset: Int = 0): [Movie] @cypher(statement: "MATCH (this)-[:IN_GENRE]->(:Genre)<-[:IN_GENRE]-(o:Movie) RETURN o ORDER BY COUNT(*) DESC")
}

The field similar will be resolved using the Cypher query

MATCH (this)-[:IN_GENRE]->(:Genre)<-[:IN_GENRE]-(o:Movie) RETURN o ORDER BY COUNT(*) DESC

to find movies with overlapping Genres.

Querying a GraphQL field marked with a @cypher directive executes that query as a subquery:

GraphQL:

{
  Movie(title: "River Runs Through It, A") {
    title
    year
    imdbRating
    actors {
      name
    }
    similar(first: 3) {
      title
    }
  }
}

Cypher:

MATCH (movie:Movie {title: "River Runs Through It, A"})
RETURN movie { .title , .year , .imdbRating,
  actors: [(movie)<-[:ACTED_IN]-(movie_actors:Actor) | movie_actors { .name }],
  similar: [ x IN apoc.cypher.runFirstColumn("
        WITH {this} AS this
        MATCH (this)-[:IN_GENRE]->(:Genre)<-[:IN_GENRE]-(o:Movie)
        RETURN o",
        {this: movie}, true) | x { .title }][..3]
} AS movie
SKIP 0

Query Neo4j

Inject a Neo4j driver instance in the context of each GraphQL request and neo4j-graphql-py will query the Neo4j database and return the results to resolve the GraphQL query.

from neo4j_graphql_py import make_executable_schema
schema = make_executable_schema(type_defs, resolvers)
import neo4j
def context(request):
    global driver
    if driver is None:
        driver = neo4j.GraphDatabase.driver("bolt://localhost:7687", auth=("neo4j", "neo4j"))

    return {'driver': driver, 'request': request}
from ariadne.asgi import GraphQL
import uvicorn
rootValue = {}
app = GraphQL(schema=schema, root_value=rootValue, context_value=context, debug=True)
uvicorn.run(app)

See /examples for complete examples using different GraphQL server libraries.

Benefits

  • Send a single query to the database
  • No need to write queries for each resolver
  • Exposes the power of the Cypher query language through GraphQL

Examples

See /examples for complete examples using different GraphQL server libraries.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].