Skip to content

Commit

Permalink
Add OrientDB example (#217)
Browse files Browse the repository at this point in the history
* Add OrientDB example

* Added disclamier

* Added disclaimer

* Testing markdown feature

* Added reference to the game of graphql repo for end-to-end example

* Removed mention of end-to-end example in game of graphql

* Updated schema generation docs to reflect README example

* Improved doc of get_graphql_schema_from_orientdb_schema_data

* Fixed documentation of get_graphql_schema_from_schema_graph

* Changed code sample title and fixed link
  • Loading branch information
pmantica1 authored and bojanserafimov committed Mar 28, 2019
1 parent 80844a2 commit eec6f3c
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 54 deletions.
134 changes: 89 additions & 45 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ python -m graphql_compiler.tool <input_file.graphql >output_file.graphql
It's modeled after Python's `json.tool`, reading from stdin and writing to stdout.

## Table of contents
* [FAQ](#faq)
* [Features](#features)
* [Querying OrientDB with GraphQL](#querying-orientdb-with-graphql)
* [Definitions](#definitions)
* [Directives](#directives)
* [@optional](#optional)
Expand Down Expand Up @@ -56,64 +57,68 @@ It's modeled after Python's `json.tool`, reading from stdin and writing to stdou
* [Miscellaneous](#miscellaneous)
* [Expanding `@optional` vertex fields](#expanding-optional-vertex-fields)
* [Optional `type_equivalence_hints` compilation parameter](#optional-type_equivalence_hints-parameter)
* [FAQ](#faq)
* [License](#license)

## FAQ

**Q: Does the compiler support all GraphQL language features?**

A: No. We prioritized and implemented a subset of all functionality supported by the
GraphQL language. We hope to add more functionality over time.

**Q: Do you really use GraphQL, or do you just use GraphQL-like syntax?**

A: We really use GraphQL. Any query that the compiler will accept is entirely valid GraphQL,
and we actually use the Python port of the GraphQL core library for parsing and type checking.
However, since the database queries produced by compiling GraphQL are subject to the limitations
of the database system they run on, our execution model is somewhat different compared to
the one described in the standard GraphQL specification. See the
[Execution model](#execution-model) section for more details.

**Q: Does this project come with a GraphQL server implementation?**

A: No -- there are many existing frameworks for running a web server. We simply built a tool
that takes GraphQL query strings (and their parameters) and returns a query string you can
use with your database. The compiler does not execute the query string against the database,
nor does it deserialize the results. Therefore, it is agnostic to the choice of
server framework and database client library used.

**Q: What databases and query languages does the compiler support?**

A: We currently support a single graph database, OrientDB version 2.2.28+, and two query languages
that OrientDB supports: the OrientDB dialect of `gremlin`, and OrientDB's own custom SQL-like
query language that we refer to as `MATCH`, after the name of its graph traversal operator.
With OrientDB, `MATCH` should be the preferred choice for most users, since it tends to run
faster than `gremlin`, and has other desirable properties. See the
[Execution model](#execution-model) section for more details.
## Features
* **Databases and Query Languages:** We currently support a single database, OrientDB version 2.2.28+, and two query languages that OrientDB supports: the OrientDB dialect of gremlin, and OrientDB's own custom SQL-like query language that we refer to as MATCH, after the name of its graph traversal operator. With OrientDB, MATCH should be the preferred choice for most users, since it tends to run faster than gremlin, and has other desirable properties. See the Execution model section for more details.

Support for relational databases including PostgreSQL, MySQL, SQLite,
and Microsoft SQL Server is a work in progress. A subset of compiler features are available for
these databases. See the [SQL](#sql) section for more details.
* **GraphQL Language Features:** We prioritized and implemented a subset of all functionality supported by the GraphQL language. We hope to add more functionality over time.

**Q: Do you plan to support other databases / more GraphQL features in the future?**
## Querying OrientDB with GraphQL
```python3
from graphql_compiler import (
get_graphql_schema_from_orientdb_schema_data, graphql_to_match
)
from graphql_compiler.schema_generation.utils import ORIENTDB_SCHEMA_RECORDS_QUERY
from graphql_compiler.tests.conftest import init_integration_graph_client

A: We'd love to, and we could really use your help! Please consider contributing to this project
by opening issues, opening pull requests, or participating in discussions.
# The following code is meant to serve as a mock example and will not run
# unless you are in the development enviroment outlined by CONTRIBUTING.md.

**Q: I think I found a bug, what do I do?**
# Step 1: Initialize dummy OrientDB database and get pyorient OrientDB client
client = init_integration_graph_client()

A: Please check if an issue has already been created for the bug, and open a new one if not.
Make sure to describe the bug in as much detail as possible, including any stack traces or
error messages you may have seen, which database you're using, and what query you compiled.
# Step 2: Generate GraphQL schema from queried OrientDB schema records
schema_records = client.command(ORIENTDB_SCHEMA_RECORDS_QUERY)
schema_data = [x.oRecordData for x in schema_records]
schema, type_equivalence_hints = get_graphql_schema_from_orientdb_schema_data(schema_data)

**Q: I think I found a security vulnerability, what do I do?**
# Step 3: Write GraphQL query to get the names of all animals with a particular net worth
# Note that we prefix net_worth with '$' and surround it with quotes to indicate it's a parameter
graphql_query = '''
{
Animal {
name @output(out_name: "animal_name")
net_worth @filter(op_name: "=", value: ["$net_worth"])
}
}
'''
parameters = {
'net_worth': '100',
}

A: Please reach out to us at
[graphql-compiler-maintainer@kensho.com](mailto:graphql-compiler-maintainer@kensho.com)
so we can triage the issue and take appropriate action.
# Step 4: Use autogenerated GraphQL schema to compile GraphQL query into Match, an OrientDB query
compilation_result = graphql_to_match(schema, graphql_query, parameters, type_equivalence_hints)

# Step 5: Run query in OrientDB
query = compilation_result.query
results = [row.oRecordData for row in client.command(query)]
assert results == [{'animal_name': 'Animal 1'}]
```
## Definitions

- **GraphQLSchema object**- To be able to compile GraphQL, the first thing you will need is a GraphQLSchema object describing
the underlying database. To build it you can use `get_graphql_schema_from_orientdb_schema_data` as
demonstrated in the code example below.
```python
# Generate GraphQL schema from queried OrientDB schema records
schema_records = client.command(ORIENTDB_SCHEMA_RECORDS_QUERY)
schema_data = [x.oRecordData for x in schema_records]
schema, type_equivalence_hints = get_graphql_schema_from_orientdb_schema_data(schema_data)
```
- **Vertex field**: A field corresponding to a vertex in the graph. In the below example, `Animal`
and `out_Entity_Related` are vertex fields. The `Animal` field is the field at which querying
starts, and is therefore the **root vertex field**. In any scope, fields with the prefix `out_`
Expand Down Expand Up @@ -1486,6 +1491,45 @@ would enable the use of a `@fold` on the `adjacent_animal` vertex field of `Foo`
}
```

## FAQ

**Q: Do you really use GraphQL, or do you just use GraphQL-like syntax?**

A: We really use GraphQL. Any query that the compiler will accept is entirely valid GraphQL,
and we actually use the Python port of the GraphQL core library for parsing and type checking.
However, since the database queries produced by compiling GraphQL are subject to the limitations
of the database system they run on, our execution model is somewhat different compared to
the one described in the standard GraphQL specification. See the
[Execution model](#execution-model) section for more details.

**Q: Does this project come with a GraphQL server implementation?**

A: No -- there are many existing frameworks for running a web server. We simply built a tool
that takes GraphQL query strings (and their parameters) and returns a query string you can
use with your database. The compiler does not execute the query string against the database,
nor does it deserialize the results. Therefore, it is agnostic to the choice of
server framework and database client library used.

**Q: Do you plan to support other databases / more GraphQL features in the future?**

A: We'd love to, and we could really use your help! Please consider contributing to this project
by opening issues, opening pull requests, or participating in discussions.

**Q: I think I found a bug, what do I do?**

A: Please check if an issue has already been created for the bug, and open a new one if not.
Make sure to describe the bug in as much detail as possible, including any stack traces or
error messages you may have seen, which database you're using, and what query you compiled.

**Q: I think I found a security vulnerability, what do I do?**

A: Please reach out to us at
[graphql-compiler-maintainer@kensho.com](mailto:graphql-compiler-maintainer@kensho.com)
so we can triage the issue and take appropriate action.




## License

Licensed under the Apache 2.0 License. Unless required by applicable law or agreed to in writing,
Expand Down
7 changes: 2 additions & 5 deletions graphql_compiler/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,7 @@ def get_graphql_schema_from_orientdb_schema_data(schema_data, class_to_field_typ
Args:
schema_data: list of dicts describing the classes in the OrientDB schema. The following
format is the way the data is structured in OrientDB 2. See
test_get_graphql_schema_from_orientdb_schema in
graphql_compiler/tests/integration_tests/test_backends_integration.py
for an example of how to query this data.
the README.md file for an example of how to query this data.
Each dict has the following string fields:
- name: string, the name of the class.
- superClasses (optional): list of strings, the name of the class's
Expand Down Expand Up @@ -189,8 +187,7 @@ def get_graphql_schema_from_orientdb_schema_data(schema_data, class_to_field_typ
Returns:
tuple of (GraphQL schema object, GraphQL type equivalence hints dict).
The tuple is of type (GraphQLSchema, GraphQLUnionType).
We hide classes with no properties in the schema since they're not representable in GraphQL.
The tuple is of type (GraphQLSchema, {GraphQLObjectType -> GraphQLUnionType}).
"""
if class_to_field_type_overrides is None:
class_to_field_type_overrides = dict()
Expand Down
2 changes: 1 addition & 1 deletion graphql_compiler/schema_generation/graphql_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ def get_graphql_schema_from_schema_graph(schema_graph, class_to_field_type_overr
Returns:
tuple of (GraphQL schema object, GraphQL type equivalence hints dict).
The tuple is of type (GraphQLSchema, GraphQLUnionType).
The tuple is of type (GraphQLSchema, {GraphQLObjectType -> GraphQLUnionType}).
"""
_validate_overriden_fields_are_not_defined_in_superclasses(class_to_field_type_overrides,
schema_graph)
Expand Down
4 changes: 1 addition & 3 deletions graphql_compiler/schema_generation/schema_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -207,9 +207,7 @@ def __init__(self, schema_data):
Args:
schema_data: list of dicts describing the classes in the OrientDB schema. The following
format is the way the data is structured in OrientDB 2. See
test_get_graphql_schema_from_orientdb_schema in
graphql_compiler/tests/integration_tests/test_backends_integration.py
for an example of how to query this data.
the README.md file for an example of how to query this data.
Each dict has the following string fields:
- name: string, the name of the class.
- superClasses (optional): list of strings, the name of the class's
Expand Down

0 comments on commit eec6f3c

Please sign in to comment.