From 4a621907e8e4ea2b637118d05cf1ca2b5b78a043 Mon Sep 17 00:00:00 2001 From: Amartya Shankha Biswas Date: Mon, 21 May 2018 14:04:08 -0400 Subject: [PATCH 1/3] Updated documentation --- README.md | 96 ++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index a8c1f4d43..a6d3c8451 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ It's modeled after Python's `json.tool`, reading from stdin and writing to stdou * [The GraphQL schema](#the-graphql-schema) * [Execution model](#execution-model) * [Miscellaneous](#miscellaneous) - * [Traversing within `@optional`](#traversing-within-optional) + * [Expanding `@optional` vertex fields](#expanding-optional-vertex-fields) * [Optional `type_equivalence_hints` compilation parameter](#optional-type_equivalence_hints-parameter) * [License](#license) @@ -169,7 +169,7 @@ For each `Animal`: - `@optional` can only be applied to vertex fields, except the root vertex field. - It is allowed to expand vertex fields within an `@optional` scope. However, doing so is currently associated with a performance penalty in `MATCH`. - For more detail, see: [Traversing within `@optional`](#traversing-within-optional-optional-). + For more detail, see: [Expanding `@optional` vertex fields](#expanding-optional-vertex-fields). - `@recurse`, `@fold`, or `@output_source` may not be used at the same vertex field as `@optional`. - `@optional`, `@output_source` and `@fold` may not be used anywhere within a scope marked `@optional`. @@ -961,9 +961,10 @@ the opposite order: ## Miscellaneous -### Traversing within [`@optional`](#optional) +### Expanding [`@optional`](#optional) vertex fields Including an optional statement in GraphQL has no performance issues on its own, -but if you continue traversing within an optional there may be significant performance implications. +but if you continue expanding vertex fields within an optional, +there may be significant performance implications. Going forward, we will refer to two different kinds of `@optional` directives. @@ -983,12 +984,18 @@ For example: OrientDB `MATCH` currently allows the last step in any traversal to be optional. Therefore, the equivalent `MATCH` traversal for the above `GraphQL` is as follows: ``` -MATCH { - class: Animal, - as: Animal___1 -}.in('Animal_ParentOf') { - as: Animal__in_Animal_ParentOf___1 -} +SELECT + Animal___1.name as `name`, + Animal__in_Animal_ParentOf___1.name as `parent_name` +FROM ( + MATCH { + class: Animal, + as: Animal___1 + }.in('Animal_ParentOf') { + as: Animal__in_Animal_ParentOf___1 + } + RETURN $matches +) ``` - A *"compound"* optional is a vertex with an `@optional` directive which does expand @@ -1011,41 +1018,58 @@ Currently, this cannot represented by a simple `MATCH` query. Specifically, the following is *NOT* a valid `MATCH` statement, because the optional traversal follows another edge: ``` -MATCH { - class: Animal, - as: Animal___1 -}.in('Animal_ParentOf') { - optional: true, - as: Animal__in_Animal_ParentOf___1 -}.in('Animal_ParentOf') { - as: Animal__in_Animal_ParentOf__in_Animal_ParentOf___1 -} +-- NOT A VALID QUERY +SELECT + Animal___1.name as `name`, + Animal__in_Animal_ParentOf___1.name as `parent_name` +FROM ( + MATCH { + class: Animal, + as: Animal___1 + }.in('Animal_ParentOf') { + optional: true, + as: Animal__in_Animal_ParentOf___1 + }.in('Animal_ParentOf') { + as: Animal__in_Animal_ParentOf__in_Animal_ParentOf___1 + } + RETURN $matches +) ``` Instead, we represent a *compound* optional by taking an union (`UNIONALL`) of two distinct `MATCH` queries. For instance, the `GraphQL` query above can be represented as follows: ``` +SELECT EXPAND($final_match) LET $match1 = ( - MATCH { - class: Animal, - as: Animal___1, - where: ( - (in_Animal_ParentOf IS null) - OR - (in_Animal_ParentOf.size() = 0) - ), - } + SELECT + Animal___1.name AS `name` + FROM ( + MATCH { + class: Animal, + as: Animal___1, + where: ( + (in_Animal_ParentOf IS null) + OR + (in_Animal_ParentOf.size() = 0) + ), + } + ) ), $match2 = ( - MATCH { - class: Animal, - as: Animal___1 - }.in('Animal_ParentOf') { - as: Animal__in_Animal_ParentOf___1 - }.in('Animal_ParentOf') { - as: Animal__in_Animal_ParentOf__in_Animal_ParentOf___1 - } + SELECT + Animal___1.name AS `name`, + Animal__in_Animal_ParentOf___1.name AS `parent_name` + FROM ( + MATCH { + class: Animal, + as: Animal___1 + }.in('Animal_ParentOf') { + as: Animal__in_Animal_ParentOf___1 + }.in('Animal_ParentOf') { + as: Animal__in_Animal_ParentOf__in_Animal_ParentOf___1 + } + ) ), $final_match = UNIONALL($match1, $match2) ``` From e0dd2a9156157e92e222abe8272acfb8187375dd Mon Sep 17 00:00:00 2001 From: Amartya Shankha Biswas Date: Mon, 21 May 2018 14:05:31 -0400 Subject: [PATCH 2/3] Updated documentation --- README.md | 62 +++++++++++++++++++++++++++---------------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/README.md b/README.md index a6d3c8451..e40580649 100644 --- a/README.md +++ b/README.md @@ -1041,37 +1041,37 @@ Instead, we represent a *compound* optional by taking an union (`UNIONALL`) of t ``` SELECT EXPAND($final_match) LET -$match1 = ( - SELECT - Animal___1.name AS `name` - FROM ( - MATCH { - class: Animal, - as: Animal___1, - where: ( - (in_Animal_ParentOf IS null) - OR - (in_Animal_ParentOf.size() = 0) - ), - } - ) -), -$match2 = ( - SELECT - Animal___1.name AS `name`, - Animal__in_Animal_ParentOf___1.name AS `parent_name` - FROM ( - MATCH { - class: Animal, - as: Animal___1 - }.in('Animal_ParentOf') { - as: Animal__in_Animal_ParentOf___1 - }.in('Animal_ParentOf') { - as: Animal__in_Animal_ParentOf__in_Animal_ParentOf___1 - } - ) -), -$final_match = UNIONALL($match1, $match2) + $match1 = ( + SELECT + Animal___1.name AS `name` + FROM ( + MATCH { + class: Animal, + as: Animal___1, + where: ( + (in_Animal_ParentOf IS null) + OR + (in_Animal_ParentOf.size() = 0) + ), + } + ) + ), + $match2 = ( + SELECT + Animal___1.name AS `name`, + Animal__in_Animal_ParentOf___1.name AS `parent_name` + FROM ( + MATCH { + class: Animal, + as: Animal___1 + }.in('Animal_ParentOf') { + as: Animal__in_Animal_ParentOf___1 + }.in('Animal_ParentOf') { + as: Animal__in_Animal_ParentOf__in_Animal_ParentOf___1 + } + ) + ), + $final_match = UNIONALL($match1, $match2) ``` In the first case where the optional edge is not followed, we have to explicitly filter out all vertices where the edge *could have been followed*. From a6948a951275c398b20fc46efa8adda6d9d9d42a Mon Sep 17 00:00:00 2001 From: Amartya Shankha Biswas Date: Mon, 21 May 2018 14:17:00 -0400 Subject: [PATCH 3/3] Updated documentation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index e40580649..ce1053f39 100644 --- a/README.md +++ b/README.md @@ -963,7 +963,7 @@ the opposite order: ### Expanding [`@optional`](#optional) vertex fields Including an optional statement in GraphQL has no performance issues on its own, -but if you continue expanding vertex fields within an optional, +but if you continue expanding vertex fields within an optional scope, there may be significant performance implications. Going forward, we will refer to two different kinds of `@optional` directives.