You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: readme.adoc
+62-49Lines changed: 62 additions & 49 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,7 +1,10 @@
1
1
= JVM Library to translate GraphQL queries and mutations to Neo4j's Cypher
2
2
:version: 1.0.0
3
+
:toc:
4
+
:toclevels: 1
5
+
:toc-title: Quick Links
3
6
4
-
This is a GraphQL transpiler written in Kotlin.
7
+
This is a https://graphql.org[GraphQL] to https://neo4j.com/developer/cypher[Cypher] transpiler written in Kotlin.
5
8
6
9
License: Apache 2.
7
10
@@ -16,17 +19,19 @@ Those Cypher queries can then executed, e.g via the Neo4j-Java-Driver (or other
16
19
17
20
The request, result and error handling is not part of this library, but we provide demo programs on how to use it in different languages.
18
21
19
-
NOTE: All the <<features|supported features>> are listed and explained below, more detailed docs will be added in time.
22
+
NOTE: All the <<features,supported features>> are listed and explained below, more detailed docs will be added in time.
20
23
21
24
== FAQ
22
25
23
26
=== How does this relate to the other neo4j graphql libraries?
24
27
25
-
Similar to `neo4j-graphql-js` this library focuses on query translation, just for the *JVM* instead of Node.js.
28
+
https://grandstack.io[The GRANDstack^] is a full-stack package that integrates React frontends via GraphQL through `neo4j-graphql-js` with Neo4j.
29
+
30
+
Similar to https://grandstack.io/docs/neo4j-graphql-js-quickstart[`neo4j-graphql-js`] this library focuses on query translation, just for the *JVM* instead of Node.js.
26
31
It does not provide a server (except as examples) or other facilities but is meant to be used as a dependency included for a single purpose.
27
32
28
-
If this library is feature complete we plan to replace the code in the current Neo4j server plugin `neo4j-graphql` with a single call to this library.
29
-
The server plugin would still handle request-response and error-handling, and perhaps some schema management but be slimmed down to a tiny piece.
33
+
We plan to replace the code in the current Neo4j server plugin `neo4j-graphql` with a single call to this library.
34
+
The server plugin could still exist as an example that shows how to handle request-response and error-handling, and perhaps some minimal schema management but be slimmed down to a tiny piece of code.
30
35
31
36
=== How does this related to graphql-java
32
37
@@ -37,6 +42,8 @@ If you wanted, you could combine `graphql-java` resolvers with this library to h
37
42
38
43
Thanks a lot to the maintainers of `graphql-java` for the awesome library.
39
44
45
+
NOTE: We also use `neo4j-opencypher-dsl` provided graciously by the spring-data-neo4j-rx project to generate parts of the cypher queries.
46
+
40
47
== Usage
41
48
42
49
You can use the library as dependency: `org.neo4j:neo4j-graphql-java:{version}` in any JVM program.
@@ -61,8 +68,6 @@ val query = """ { p:personByName(name:"Joe") { age } } """
This example doesn't handle introspection queries but the one in the test directory does.
196
+
This example doesn't handle introspection queries, but the one in the test directory does.
191
197
192
198
== Advanced Queries
193
199
@@ -239,6 +245,7 @@ This example doesn't handle introspection queries but the one in the test direct
239
245
* @cypher directive for top level queries and mutations, supports arguments
240
246
* date(time)
241
247
* interfaces
248
+
* complex filter parameters, with optional query optimization strategy
242
249
243
250
=== Next
244
251
@@ -253,16 +260,16 @@ This example doesn't handle introspection queries but the one in the test direct
253
260
254
261
=== Parse SDL schema
255
262
256
-
Currently schemas with object types, enums, fragments and Query types are parsed and handled.
257
-
We support @relation directives on fields and types for rich relationships
258
-
We support @cypher directives on fields and top-level query and mutation fields.
259
-
The configurable augmentation auto-generates queries and mutations (create,update,delete) for all types.
260
-
It supports the built-in scalars for GraphQL.
261
-
For arguments we support input types in many places and filters as known from GraphCool/Prisma.
263
+
* Currently schemas with object types, enums, fragments and Query types are parsed and handled.
264
+
* `@relation` directives on fields and types for rich relationships
265
+
* `@cypher` directives on fields and top-level query and mutation fields.
266
+
* The configurable augmentation auto-generates queries and mutations (create,update,delete) for all types.
267
+
* Supports the built-in scalars for GraphQL.
268
+
* For arguments input types in many places and filters from GraphCool/Prisma.
262
269
263
270
=== Resolve query Fields via Result Types
264
271
265
-
For _query fields_ that result in object types (even if wrapped in list/non-null), the appropriate object type is found in the schema and used to translate the query.
272
+
For _query fields_ that result in object types (even if wrapped in list/non-null), the appropriate object type is determined via the schema and used to translate the query.
MATCH (person:Person) WHERE person.name = 'Joe' AND person.age = 42 RETURN person { .name } AS person
297
304
----
298
305
299
-
Only that the literal values are turned into parameters.
306
+
The literal values are turned into Cypher query parameters.
300
307
301
308
=== Handle Relationships via @relation Directive on Schema Fields
302
309
303
-
If you want to represent a relationship from the graph in GraphQL you have to add an `@relation` directive that contains the relationship-type and the direction.
304
-
Default relationship-type is 'OUT'.
310
+
If you want to represent a relationship from the graph in GraphQL you have to add a `@relation` directive which contains the relationship-type and the direction.
311
+
The default relationship-type is 'OUT'.
305
312
So you can use different domain names in your GraphQL fields that are independent of your graph model.
306
313
307
314
[source,graphql]
@@ -323,6 +330,7 @@ person(name:"Keanu Reeves") {
323
330
----
324
331
325
332
NOTE: We use Neo4j's _pattern comprehensions_ to represent nested graph patterns in Cypher.
333
+
This will be updated to subqueries from 4.1
326
334
327
335
=== Handle first, offset Arguments
328
336
@@ -343,13 +351,13 @@ MATCH (person:Person) RETURN person { .name } AS person SKIP 5 LIMIT 10
343
351
344
352
=== Argument Types: string, int, float, array
345
353
346
-
The default Neo4j types are handled both as argument types as well as field types.
354
+
The default Neo4j Cypher types are handled both as argument types as well as field types.
347
355
348
-
NOTE: Datetime and spatial not yet.
356
+
NOTE: Spatial is not yet covered.
349
357
350
358
=== Usage of ID
351
359
352
-
Each type is expect to have exactly one filed of type `ID` defined.
360
+
Each type is expected to have exactly one filed of type `ID` defined.
353
361
If the field is named `_id`, it is interpreted as the database internal graph ID.
354
362
355
363
So there are 3 cases:
@@ -383,17 +391,17 @@ type User {
383
391
}
384
392
----
385
393
386
-
IMPORTANT: For the auto generated queries and mutations the `ID` field is used primarily.
394
+
IMPORTANT: For the auto generated queries and mutations the `ID` field is used as _primary key_.
387
395
388
-
TIP: You should create an unique index on the `ID` fields
396
+
TIP: You should create a unique constraint on the `ID` fields
389
397
390
398
=== Parameter Support
391
399
392
-
We handle passed in GraphQL parameters, these are resolved correctly when used within the GraphQL query.
400
+
GraphQL parameters are passed onto Cypher, these are resolved correctly when used within the GraphQL query.
393
401
394
402
=== Parametrization
395
403
396
-
As we don't want to have literal values in our Cypher queries, all of them are translated into parameters.
404
+
For query injection prevention and caching purposes, literal values are translated into parameters.
397
405
398
406
[source,graphql]
399
407
----
@@ -406,7 +414,10 @@ to
406
414
407
415
[source,cypher]
408
416
----
409
-
MATCH (person:Person) WHERE person.name = $personName AND person.age = $personAge RETURN person { .name } AS person LIMIT $first
417
+
MATCH (person:Person)
418
+
WHERE person.name = $personName AND person.age = $personAge
419
+
RETURN person { .name } AS person
420
+
LIMIT $first
410
421
----
411
422
412
423
Those parameters are returned as part of the `Cypher` type that's returned from the `translate()` method.
@@ -452,7 +463,7 @@ ORDER BY person.name ASC, person.age DESC
452
463
----
453
464
454
465
455
-
NOTE: Those enums are not yet automatically generated. And we don't support ordering yet on nested, related fields.
466
+
NOTE: We don't yet support ordering on nested relationship fields.
Filters are a powerful way of selecting a subset of data.
498
-
Inspired by the https://www.graph.cool/docs/reference/graphql-api/query-api-nia9nushae[graph.cool/Prisma filter approach], our filters work the same way.
499
-
500
-
NOTE: we'll create more detailed docs, for now the prisma docs on that topic are pretty good.
509
+
Inspired by the https://www.graph.cool/docs/reference/graphql-api/query-api-nia9nushae[graph.cool/Prisma filter approach^], our filters work the same way.
501
510
511
+
These filters are documented in detail in the https://grandstack.io/docs/graphql-filtering [GRANDstack docs^].
502
512
503
-
We use nested input types for arbitrary filtering on query types and fields
513
+
We use nested input types for arbitrary filtering on query types and fields.
504
514
505
515
[source,graphql]
506
516
----
@@ -521,8 +531,6 @@ You can also apply nested filter on relations, which use suffixes like `("",not,
521
531
}
522
532
----
523
533
524
-
NOTE: Those nested input types are not yet generated, we use leniency in the parser.
525
-
526
534
==== Optimized Filters
527
535
528
536
If you encounter performance problems with the cypher queries generated for the filter,
@@ -574,8 +582,10 @@ query {
574
582
=== @cypher Directives
575
583
576
584
With `@cypher` directives you can add the power of Cypher to your GraphQL API.
577
-
It allows you, without code to compute field values using complex queries.
578
-
You can also write your own, custom top-level queries and mutations using Cypher.
585
+
586
+
It allows you, without code to *compute field values* using complex queries.
587
+
588
+
You can also write your own, *custom top-level queries and mutations* using Cypher.
579
589
580
590
Arguments on the field are passed to the Cypher statement as parameters.
581
591
Input types are supported, they appear as `Map` type in your Cypher statement.
@@ -590,19 +600,22 @@ NOTE: Those Cypher directive queries are only included in the generated Cypher s
0 commit comments