diff --git a/data-explorer/kusto/query/graph-query-language-clauses.md b/data-explorer/kusto/query/graph-query-language-clauses.md index 0479c71f5f..f575db9768 100644 --- a/data-explorer/kusto/query/graph-query-language-clauses.md +++ b/data-explorer/kusto/query/graph-query-language-clauses.md @@ -25,14 +25,14 @@ Use `WHERE` after the pattern to compare element properties with operators such ```gql match (p:Person)-[:ACTED_IN]->(m:Movie) -where (p.Name = 'Actor1' or p.Name = 'Actor3') and m.Title <> 'Movie1' and p.Born > 1901 +where (p.Name = 'Tom' or p.Name = 'Ron') and m.Title <> 'T1' and p.Born > 1901 return p.Name as name, m.Title as title ``` |name|title| |---|---| -|Actor1|Movie3| -|Actor1|Movie2| +|Tom|T3| +|Tom|T2| ### Negate a condition with NOT @@ -47,7 +47,7 @@ return p.Name as name |name| |---| -|Actor4| +|Julia| The following two queries are equivalent. The first uses prefix `NOT`; the second uses the inline `NOT CONTAINS` predicate: @@ -60,7 +60,8 @@ return p.Name as name |name| |---| -|Actor4| +|Tom| +|Julia| ```gql @@ -71,7 +72,8 @@ return p.Name |name| |---| -|Actor4| +|Tom| +|Julia| ### Inline property filters @@ -79,24 +81,24 @@ An inline `{property: value}` inside an element pattern is shorthand for an equa ```gql -match (p:Person {Name: 'Actor1'}) +match (p:Person {Name: 'Tom'}) return p.Name as name, p.Born as born ``` |name|born| |---|---| -|Actor1|1956| +|Tom|1956| ```gql match (p:Person) -where p.Name = 'Actor1' +where p.Name = 'Tom' return p.Name as name, p.Born as born ``` |name|born| |---|---| -|Actor1|1956| +|Tom|1956| Inline filters apply to edges as well as nodes: @@ -108,74 +110,74 @@ return p.Name as name, m.Title as title |name|title| |---|---| -|Actor2|Movie1| +|Kevin|T1| ### Multiple inline conditions -List several properties in one inline filter to require all of them; the pairs are combined with `AND`. This pattern matches only `Person` nodes where both `Name` is `'Actor1'` and `Born` is `1956`: +List several properties in one inline filter to require all of them; the pairs are combined with `AND`. This pattern matches only `Person` nodes where both `Name` is `'Tom'` and `Born` is `1956`: ```gql -match (p:Person {Name: 'Actor1', Born: 1956}) +match (p:Person {Name: 'Tom', Born: 1956}) return p.Name as name, p.Born as born ``` |name|born| |---|---| -|Actor1|1956| +|Tom|1956| Apply inline filters to several elements in the same pattern to constrain each node and edge at once: ```gql -match (p:Person {Name: 'Actor2'})-[:ACTED_IN {Role: 'Role2'}]->(m:Movie {Title: 'Movie1'}) +match (p:Person {Name: 'Kevin'})-[:ACTED_IN {Role: 'Role2'}]->(m:Movie {Title: 'T1'}) return p.Name as name, m.Title as title ``` |name|title| |---|---| -|Actor2|Movie1| +|Kevin|T1| Inline filters and `WHERE` combine freely: use inline `{...}` for the equality checks and `WHERE` for everything else, such as ranges or `OR`: ```gql -match (p:Person {Name: 'Actor1'})-[:ACTED_IN]->(m:Movie) +match (p:Person {Name: 'Tom'})-[:ACTED_IN]->(m:Movie) where m.Year >= 1990 return p.Name as name, m.Title as title ``` |name|title| |---|---| -|Actor1|Movie1| -|Actor1|Movie2| -|Actor1|Movie3| +|Tom|T1| +|Tom|T2| +|Tom|T3| Inside a node or edge: ```gql -match (p:Person)-[e where 'DIRECTED' in labels(e)]->(m:Movie where m.Title <> 'Movie1') +match (p:Person)-[e where 'DIRECTED' in labels(e)]->(m:Movie where m.Title <> 'T1') return p.Name as name, m.Title as title ``` |name|title| |---|---| -|Actor1|Movie2| +|Tom|T2| The `IN` predicate tests whether a value is one of the items in a list: ```gql match (p:Person) -where p.Name in ['Actor1', 'Actor2'] +where p.Name in ['Tom', 'Kevin'] return p.Name as name ``` |name| |---| -|Actor1| -|Actor2| +|Tom| +|Kevin| To compare entities, use `element_id(n)` or property comparisons (`n.Name <> m.Name`); direct entity equality isn't supported. @@ -191,10 +193,10 @@ return m.Title as Title, p.Name as Name |Title|Name| |---|---| -|Movie3|Actor1| -|Movie2|Actor1| -|Movie1|Actor1| -|Movie1|Actor2| +|T3|Tom| +|T2|Tom| +|T1|Tom| +|T1|Kevin| Return every bound variable with `*`: @@ -206,7 +208,7 @@ return * |p|m| |---|---| -|{"Name": "Actor1", .. ,"Description": "War film","Year": 2020
}| +|{"Name": "Tom", .. ,|, .. ,"Description": "War film","Year": 2020}| ## DISTINCT @@ -222,8 +224,8 @@ return distinct p.Name as name |name| |---| -|Actor1| -|Actor2| +|Tom| +|Kevin| `DISTINCT` also works inside aggregations, to aggregate over distinct values only: @@ -235,9 +237,9 @@ return m.Title as Title, count(p.Name) as Actors, collect_list(distinct p.Name) |Title|Actors|Names| |---|---|---| -|Movie3|1|["Actor1"]| -|Movie2|1|["Actor1"]| -|Movie1|2|["Actor1","Actor2"]| +|T3|1|["Tom"]| +|T2|1|["Tom"]| +|T1|2|["Tom","Kevin"]| ## ORDER BY @@ -250,10 +252,10 @@ match (p:Person) return p.Name as name, p.Born as born order by p.Born desc |name|born| |---|---| -|Actor4|1967| -|Actor2|1958| -|Actor1|1956| -|Actor3|1954| +|Julia|1967| +|Kevin|1958| +|Tom|1956| +|Ron|1954| Sort by multiple keys, each with its own direction: @@ -266,10 +268,10 @@ order by Name desc, Title asc |Name|Title| |---|---| -|Actor1|Movie1| -|Actor1|Movie3| -|Actor1|Movie2| -|Actor2|Movie1| +|Tom|T1| +|Tom|T3| +|Tom|T2| +|Kevin|T1| > [!NOTE] > Using `ORDER BY` directly after `MATCH` might not have an effect if the query has subsequent `NEXT` or join statements. @@ -285,8 +287,8 @@ match (p:Person) return p.Name as name order by p.Born asc limit 2 |name| |---| -|Actor3| -|Actor1| +|Ron| +|Tom| ```gql @@ -295,8 +297,8 @@ match (p:Person) order by p.Born asc limit 2 return p.Name as name |name| |---| -|Actor3| -|Actor1| +|Ron| +|Tom| ## OFFSET @@ -309,7 +311,7 @@ match (m:Movie) return m.Title as title order by m.Title offset 1 limit 1 |title| |---| -|Movie3| +|T3| Like `LIMIT`, `OFFSET` can also sit directly after the `MATCH` pattern, before `RETURN`. In that position it skips matched rows before projection: @@ -320,7 +322,7 @@ match (m:Movie) order by m.Title offset 1 return m.Title as title |title| |---| -|Movie3| +|T3| ## FOR @@ -378,7 +380,7 @@ return p.Name as Name, BirthYear |Name|BirthYear| |---|---| -|Actor2|1958| +|Kevin|1958| Bind a constant and use it to filter: @@ -392,8 +394,8 @@ return m.Title as title |Title| |---| -|Movie2| -|Movie3| +|T2| +|T3| Define multiple values, where one builds on another: @@ -407,10 +409,10 @@ return p.Name as name, a, b |name|a|b| |---|---|---| -|Actor1|1|4| -|Actor2|1|4| -|Actor3|1|4| -|Actor4|1|4| +|Tom|1|4| +|Kevin|1|4| +|Ron|1|4| +|Julia|1|4| ## NEXT @@ -429,13 +431,13 @@ return Actor, Title |Actor|Title| |---|---| -|Actor1|Movie3| +|Tom|T3| Carry a path forward, then compute over it: ```gql -match p = (n0:Person)-[:DIRECTED]->(:Movie {Title: 'Movie1'}) +match p = (n0:Person)-[:DIRECTED]->(:Movie {Title: 'T1'}) return * next return p, path_length(p) as Hops @@ -446,7 +448,7 @@ Pass a node variable into a later `MATCH`: ```gql -match (p:Person {Name: 'Actor1'}) +match (p:Person {Name: 'Tom'}) return p next match (p)-[:ACTED_IN]->(m:Movie) @@ -495,7 +497,7 @@ return p.Name as name |name| |---| -|Actor1| +|Tom| ## UNION @@ -510,13 +512,13 @@ match (m:Movie) return m.Title as name |name| |---| -|Actor1| -|Actor2| -|Actor3| -|Actor4| -|Movie1| -|Movie2| -|Movie3| +|Tom| +|Kevin| +|Ron| +|Julia| +|T1| +|T2| +|T3| ## Related content diff --git a/data-explorer/kusto/query/graph-query-language-functions.md b/data-explorer/kusto/query/graph-query-language-functions.md index 29dd63ee12..b3454e0286 100644 --- a/data-explorer/kusto/query/graph-query-language-functions.md +++ b/data-explorer/kusto/query/graph-query-language-functions.md @@ -86,13 +86,13 @@ match () limit 1 return string_join(["a", "bc"], "") as result ```gql MATCH (p :Person) -WHERE p.Name starts with 'Tom' or (p.Name ends with 's' and p.Name contains 'Han') +WHERE p.Name starts with 'T' RETURN p.Name as actorName ``` |actorName| |---| -|Actor1| +|Tom| ## Numeric functions @@ -155,9 +155,9 @@ return m.Title as Title, case when m.Year < 2000 then 'C' else 'M' end as Era |Title|Era| |---|---| -|Movie1|C| -|Movie2|M| -|Movie3|M| +|T1|C| +|T2|M| +|T3|M| Simple form compares one expression against each `WHEN` value: @@ -166,17 +166,17 @@ Simple form compares one expression against each `WHEN` value: match (m:Movie) return m.Title as Title, case m.Title - when 'Movie1' then 'A' - when 'Movie3' then 'G' + when 'T1' then 'A' + when 'T3' then 'G' else 'O' end as Name ``` |Title|Name| |---|---| -|Movie1|A| -|Movie2|O| -|Movie3|G| +|T1|A| +|T2|O| +|T3|G| > [!NOTE] > Every `CASE` expression must include an `ELSE` clause. A `CASE` without `ELSE` isn't supported. @@ -199,10 +199,10 @@ return m.Title as Title, cast(nodes(p)[0].Born as int) as ActorBorn |Title|ActorBorn| |---|---| -|Movie3|1956| -|Movie2|1956| -|Movie1|1956| -|Movie1|1958| +|T3|1956| +|T2|1956| +|T1|1956| +|T1|1958| ```gql @@ -212,10 +212,10 @@ RETURN p.Name || ', ' || CAST(p.Born as string) as nameAndYear |nameAndYear| |---| -|Actor1, 1956| -|Actor2, 1958| -|Actor3, 1954| -|Actor4, 1967| +|Tom, 1956| +|Kevin, 1958| +|Ron, 1954| +|Julia, 1967| **Aggregating on object keys.** An aggregation key can't be an object (`dynamic`) value such as a node, edge, or property map. Convert the object value to a string first, using `to_json_string(...)` or `CAST(... AS string)`. @@ -227,9 +227,9 @@ return to_json_string(p), count(m) as participatedInMoviesCount |to_json_string(p)|participatedInMoviesCount| |---|---| -|{"Name":"Actor1", ... }|4| -|{"Name":"Actor2", ... }|1| -|{"Name":"Actor3", ... }|1| +|{"Name":"Tom", ... }|4| +|{"Name":"Kevin", ... }|1| +|{"Name":"Ron", ... }|1| ## JSON functions @@ -240,13 +240,13 @@ return to_json_string(p), count(m) as participatedInMoviesCount ```gql -MATCH (n:Person {Name: 'Actor4'}) +MATCH (n:Person {Name: 'Julia'}) RETURN TO_JSON_STRING(n) AS `json` ``` |json| |---| -|{"Name":"Actor4","Born":1967,"Label2":["Person ","Female ","BestActressAward "],"Label":"Person"}| +|{"Name":"Julia","Born":1967,"Label2":["Person ","Female ","BestActressAward "],"Label":"Person"}| > [!TIP] > The result alias `json` is escaped because json is a reserved keyword @@ -328,14 +328,14 @@ match () limit 1 return keys({"a":1, "b":2}) as my_keys ```gql MATCH (p:Person) -WHERE p.Name IN ['Actor1', 'Actor2'] +WHERE p.Name IN ['Tom', 'Kevin'] RETURN p.Name as actor ``` |actor| |---| -|Actor1| -|Actor2| +|Tom| +|Kevin| ```gql @@ -448,9 +448,9 @@ RETURN m.Title as Movie, COUNT(*) AS ActorsCount |Movie|ActorsCount| |---|---| -|Movie1|2| -|Movie2|1| -|Movie3|1| +|T1|2| +|T2|1| +|T3|1| ```gql @@ -459,7 +459,7 @@ RETURN collect_list(distinct n.Name) as actors ``` |actors| |---| -|["Actor1", "Actor2"]| +|["Tom", "Kevin"]| Find how many movies each actor acted in: @@ -471,8 +471,8 @@ RETURN TO_JSON_STRING(n) as actor, count(m) as moviesCount |actor|moviesCount| |---|---| -|{"Name":"Actor1", ... ,"Label":"Person"}|3| -|{"Name":"Actor2", ... ,"Label":"Person"}|1| +|{"Name":"Tom", ... ,"Label":"Person"}|3| +|{"Name":"Kevin", ... ,"Label":"Person"}|1| > [!NOTE] > To group by or aggregate a node, edge, or path, first convert it to a string with `TO_JSON_STRING()` or `CAST(object AS string)`, because objects can't be used as grouping keys directly. @@ -500,27 +500,27 @@ Other operators: ```gql match (p:Person) -where p.Name in ['Actor1', 'Actor4'] +where p.Name in ['Tom', 'Julia'] return p.Name as name ``` |name| |---| -|Actor1| -|Actor4| +|Tom| +|Julia| Negate the test with `NOT` to keep only values that are absent from the list: ```gql match (p:Person) -where not p.Name in ['Actor1', 'Actor2', 'Actor3'] +where not p.Name in ['Tom', 'Kevin', 'Ron'] return p.Name as name ``` |name| |---| -|Actor4| +|Julia| Other predicates: @@ -533,14 +533,14 @@ Other predicates: ```gql MATCH (p:Person) -WHERE p.Name IN ['Actor1', 'Actor2'] AND p.Born IS NOT NULL +WHERE p.Name IN ['Tom', 'Kevin'] AND p.Born IS NOT NULL RETURN p.Name as name ``` |name| |---| -|Actor1| -|Actor2| +|Tom| +|Kevin| It's possible to use `IS TRUE` or `IS FALSE` to test the result of a Boolean expression: @@ -553,7 +553,7 @@ RETURN p.Name |name| |---| -|Actor4| +|Julia| ## Related content diff --git a/data-explorer/kusto/query/graph-query-language-guide.md b/data-explorer/kusto/query/graph-query-language-guide.md index 9a2a8f5cfa..1516dfcce8 100644 --- a/data-explorer/kusto/query/graph-query-language-guide.md +++ b/data-explorer/kusto/query/graph-query-language-guide.md @@ -65,9 +65,9 @@ match (m:Movie) return m.Title as MovieTitle | MovieTitle | |---| | m.Title | -| Movie1 | -| Movie2 | -| Movie3 | +| T1 | +| T2 | +| T3 | ### Edge patterns @@ -90,10 +90,10 @@ match (p:Person)-[:ACTED_IN]->(m:Movie) return p.Name as actor, m.Title as movie |actor|movie| |---|---| -|Actor1|Movie1| -|Actor1|Movie2| -|Actor1|Movie3| -|Actor2|Movie1| +|Tom|T1| +|Tom|T2| +|Tom|T3| +|Kevin|T1| Count the matched patterns: @@ -118,8 +118,8 @@ return p1.Name as firstActor, m.Title as movie, p2.Name as secondActor |firstActor|movie|secondActor| |---|---|---| -|Actor1|Movie1|Actor2| -|Actor2|Movie1|Actor1| +|Tom|T1|Kevin| +|Kevin|T1|Tom| ### Multiple sequences (Multi-path or "star" pattern) @@ -133,9 +133,9 @@ return p.Name as person, m.Title as firstTitle, m2.Title as secondTitle |person|firstTitle|secondTitle| |---|---|---| -|Actor1|Movie1|Movie2| -|Actor1|Movie2|Movie2| -|Actor1|Movie3|Movie2| +|Tom|T1|T2| +|Tom|T2|T2| +|Tom|T3|T2| ### Variable-length edges @@ -185,7 +185,7 @@ match (p :Female) return p.Name as name |name| |---| -|Actor4| +|Julia| Next query showcases a group label expression: @@ -196,8 +196,8 @@ match ()-[e: !ACTED_IN & (DIRECTED | A) | E]->(m:Movie) return m.Title as title |title| |---| -|Movie1| -|Movie2| +|T1| +|T2| Reference the same variable with two labels to require both: @@ -208,7 +208,7 @@ match (n:Male), (n:BestActorAward) return n.Name as name |name| |---| -|Actor1| +|Tom| The [`labels()`](graph-query-language-functions.md#graph-and-path-functions) function returns an element's labels as a list. It's useful in `WHERE` and `RETURN` clauses. For example, `'DIRECTED' IN labels(e)`. @@ -220,10 +220,10 @@ return p.Name as name, labels(e) as EdgeLabels |name|EdgeLabels| |---|---| -|Actor1|["ACTED_IN"]| -|Actor1|["ACTED_IN"]| -|Actor1|["ACTED_IN"]| -|Actor2|["ACTED_IN"]| +|Tom|["ACTED_IN"]| +|Tom|["ACTED_IN"]| +|Tom|["ACTED_IN"]| +|Kevin|["ACTED_IN"]| ## Access node properties @@ -237,9 +237,9 @@ return m.Title as title, m.Year as year |title|year| |---|---| -|Movie1|1995| -|Movie2|2011| -|Movie3|2020| +|T1|1995| +|T2|2011| +|T3|2020| The `[]` indexer accesses an element of a list or path by its integer position (zero-based), not a property by name. Combine it with dot notation to read a property of a path element. For example, `p[0]` is the first node of the path `p`, so `p[0].Name` returns that node's `Name`: @@ -251,28 +251,28 @@ return p[0].Name as name |name| |---| -|Actor1| -|Actor1| -|Actor1| -|Actor2| +|Tom| +|Tom| +|Tom| +|Kevin| ## Comparisons GQL supports the standard comparison operators on scalar values: `=`, `<>` (not equal), `<`, `<=`, `>`, and `>=`. -Next query filters out movies with title 'Movie1' from matched patterns: +Next query filters out movies with title 'T1' from matched patterns: ```gql match (p:Person)-[:ACTED_IN]->(m:Movie) -where m.Title <> 'Movie1' +where m.Title <> 'T1' return p.Name as name, m.Title as title ``` |name|title| |---|---| -|Actor1|Movie2| -|Actor1|Movie3| +|Tom|T2| +|Tom|T3| You can't compare two nodes or edges directly with `=` or `<>`. To test whether two entities are different, compare their identities with [`element_id()`](graph-query-language-functions.md#graph-and-path-functions) instead. For example, the following query finds pairs of distinct actors who appeared in the same movie: @@ -285,8 +285,8 @@ return p1.Name as firstName, p2.Name as secondName, m.Title as title |firstName|secondName|title| |---|---|---| -|Actor1|Actor2|Movie1| -|Actor2|Actor1|Movie1| +|Tom|Kevin|T1| +|Kevin|Tom|T1| #### Filtering edges in a variable-length path @@ -299,8 +299,8 @@ match ()-[e:DIRECTED]->+() return e[0].Name as personName, e[0].Role as personRo |personName|personRole| |---|---| -|Actor3|Director| -|Actor1|Director| +|Ron|Director| +|Tom|Director| ```gql @@ -336,7 +336,7 @@ return to_json_string(p) as myPath |myPath| |---| -|[{"Name":"Actor2", ... "Description":"A movie about space","Year":1995}]| +|[{"Name":"Kevin", ... "Description":"A movie about space","Year":1995}]| ## Operators @@ -354,10 +354,10 @@ return p.Name || ' born ' || cast(p.Born as string) as `Label`, p.Born + 1 as Ne |Label|NextYear| |---|---| -|Actor1 born 1956|1957| -|Actor2 born 1958|1959| -|Actor3 born 1954|1955| -|Actor4 born 1967|1968| +|Tom born 1956|1957| +|Kevin born 1958|1959| +|Ron born 1954|1955| +|Julia born 1967|1968| > [!NOTE] > The `Label` variable is escaped because label is a reserved keyword. To differentiate between GQL syntax and user variables, escape user variables. Alternatively, add a prefix or suffix `_`. @@ -375,7 +375,7 @@ return `path` |path| |---| -|[{"Name": "Actor2" ,..., "Drama", "History"]}]| +|[{"Name": "Kevin" ,..., "Drama", "History"]}]| > [!TIP] > The path alias `path` is escaped because path is a reserved keyword. To differentiate between GQL syntax and user variables, you can escape user variables. Alternatively, add a prefix or suffix `_`. @@ -387,7 +387,7 @@ match p1 = (n1)-[e]->{1,2}(n2), p2 = (:Movie & War) return p1, p2 |p1|p2| |---|---| -|[{ "Name": "Actor1" ,..., "War" ]}]|[{ ,..., "War" ]}]| +|[{ "Name": "Tom" ,..., "War" ]}]|[{ ,..., "War" ]}]| The available path functions are `path_length`, `nodes`, and `edges` (also spelled `relationships`), which operate on a path variable. For details, see [Graph and path functions](graph-query-language-functions.md#graph-and-path-functions). @@ -400,7 +400,7 @@ return nodes(p)[0] as firstNode, edges(p) as `edges`, path_length(p) as pathLeng |firstNode|edges|pathLength| |---|---|---| -|{ "Name": "Actor2", ...|[ ..."ACTED_IN"... }]|1| +|{ "Name": "Kevin", ...|[ ..."ACTED_IN"... }]|1| > [!NOTE] > The `edges` variable is escaped because edges is a reserved keyword. To differentiate between GQL syntax and user variables, you can escape user variables. Alternatively, add a prefix or suffix `_`. @@ -409,13 +409,13 @@ You can combine these functions to return the nodes, edges, and length of a matc ```gql -match p = (n0:Person)-[:DIRECTED]->(m:Movie {Title: 'Movie1'}) +match p = (n0:Person)-[:DIRECTED]->(m:Movie {Title: 'T1'}) return nodes(p), edges(p), path_length(p) ``` |nodes(p)|edges(p)|path_length(p)| |---|---|---| -|[{"Name": "Actor3",...},{"Title": "Movie1", ...}]|[{..."DIRECTED"...}]|1| +|[{"Name": "Ron",...},{"Title": "T1", ...}]|[{..."DIRECTED"...}]|1| ### Shortest paths @@ -498,9 +498,9 @@ return m.Title as Title, count(*) as Actors, collect_list(p.Name) as ActorNames |Title|Actors|ActorNames| |---|---|---| -|Movie3|1|[ "Actor1"]| -|Movie2|1|[ "Actor1"]| -|Movie1|2|[ "Actor1", "Actor2"]| +|T3|1|[ "Tom"]| +|T2|1|[ "Tom"]| +|T1|2|[ "Tom", "Kevin"]| Next query calculates count of patterns: @@ -524,9 +524,9 @@ return m.Title as Title, min(p.Born) as Earliest, max(p.Born) as Latest, avg(p.B |Title|Earliest|Latest|AvgBorn| |---|---|---|---| -|Movie3|1956|1956|1956| -|Movie2|1956|1956|1956| -|Movie1|1956|1958|1957| +|T3|1956|1956|1956| +|T2|1956|1956|1956| +|T1|1956|1958|1957| `sum` adds up a numeric expression across each group: @@ -538,9 +538,9 @@ return m.Title as Title, sum(p.Born) as BornSum |Title|BornSum| |---|---| -|Movie3|1956| -|Movie2|1956| -|Movie1|3914| +|T3|1956| +|T2|1956| +|T1|3914| ### Aggregate by entity @@ -554,9 +554,9 @@ return to_json_string(m) as Movie, count(*) as Actors |Movie|Actors| |---|---| -|{"Title":"Movie3", ... }|1| -|{"Title":"Movie2", ... }|1| -|{"Title":"Movie1", ... }|2| +|{"Title":"T3", ... }|1| +|{"Title":"T2", ... }|1| +|{"Title":"T1", ... }|2| Alternatively, convert the entity to a string with `CAST(entity AS string)`. This conversion also works as a grouping key: @@ -568,9 +568,9 @@ return cast(m as string) as Movie, count(*) as Actors |Movie|Actors| |---|---| -|{"Title":"Movie3", ... }|1| -|{"Title":"Movie2", ... }|1| -|{"Title":"Movie1", ... }|2| +|{"Title":"T3", ... }|1| +|{"Title":"T2", ... }|1| +|{"Title":"T1", ... }|2| ## Composite queries @@ -581,43 +581,43 @@ A query can contain more than one `MATCH` statement. How the statements relate d ```gql match (p:Person where p.Name starts with 'J') -match (m:Movie where m.Title starts with 'G') +match (m:Movie where m.Title starts with 'T3') return p.Name as name, m.Title as title ``` |name|title| |---|---| -|Actor4|Movie3| +|Julia|T3| **Match sequence.** When a later `MATCH` reuses a variable bound by an earlier one, it continues from those bindings, joining the patterns on the shared variable. ```gql -match (p:Person {Name: 'Actor1'}) +match (p:Person {Name: 'Tom'}) match (p)-[:ACTED_IN]->(m:Movie) return m.Title as title ``` |title| |---| -|Movie3| -|Movie2| -|Movie1| +|T3| +|T2| +|T1| > [!TIP] > Each additional `MATCH` may introduce another join. Whenever a relationship can be expressed within a single pattern, prefer fewer `MATCH` statements for better performance. For example, the query above is equivalent to, and faster when written as, a single statement: ```gql - match (p:Person {Name: 'Actor1'}), (p)-[:ACTED_IN]->(m:Movie) + match (p:Person {Name: 'Tom'}), (p)-[:ACTED_IN]->(m:Movie) return m.Title as title ``` |title| |---| -|Movie3| -|Movie2| -|Movie1| +|T3| +|T2| +|T1| ## Optional match @@ -632,10 +632,10 @@ return p.Name as name, m.Title as title |name|title| |---|---| -|Actor3|Movie1| -|Actor1|Movie2| -|Actor4| | -|Actor2| | +|Ron|T1| +|Tom|T2| +|Julia| | +|Kevin| | ## Supported types @@ -643,7 +643,7 @@ GQL values map to the underlying [Kusto scalar types](scalar-data-types/index.md | Kusto type | Description | GQL literal example | |---|---|---| -| `string` | Unicode text. | `'Actor1'` | +| `string` | Unicode text. | `'Tom'` | | `bool` | Boolean value. | `true`, `false` | | `int` | 32-bit signed integer. | `42` | | `long` | 64-bit signed integer. | `9000000000` | @@ -674,10 +674,10 @@ return p.Name || ' (' || cast(p.Born as string) || ')' as `Label` |Label| |---| -|Actor1 (1956)| -|Actor2 (1958)| -|Actor3 (1954)| -|Actor4 (1967)| +|Tom (1956)| +|Kevin (1958)| +|Ron (1954)| +|Julia (1967)| > [!NOTE] > The `Label` variable is escaped because label is a reserved keyword. To differentiate between GQL syntax and user variables, you can escape user variables. Alternatively, add a prefix or suffix `_`. @@ -747,13 +747,13 @@ limit 1 ```gql -match (n:Person {Name: 'Actor4'}) +match (n:Person {Name: 'Julia'}) return to_json_string(n) as `Json` ``` |Json| |---| -|{"Name":"Actor4","Born":1967,"Label2":["Female","BestActressAward"]}| +|{"Name":"Julia","Born":1967,"Label2":["Female","BestActressAward"]}| > [!NOTE] > The `Json` variable is escaped because json is a reserved keyword. To differentiate between GQL syntax and user variables, you can escape user variables. Alternatively, add a prefix or suffix `_`. diff --git a/data-explorer/kusto/query/graph-query-language.md b/data-explorer/kusto/query/graph-query-language.md index e2c3dd3abf..962b987176 100644 --- a/data-explorer/kusto/query/graph-query-language.md +++ b/data-explorer/kusto/query/graph-query-language.md @@ -27,7 +27,7 @@ A typical GQL query starts with a `MATCH` pattern, optionally filters and aggreg ```gql MATCH (p:Person)-[:ACTED_IN]->(m:Movie) -WHERE m.Year >= 1990 AND (p.Name STARTS WITH 'T' OR p.Name STARTS WITH 'K') +WHERE m.Year >= 1990 AND p.Name STARTS WITH 'T' RETURN p.Name AS actor, COUNT(m) AS movieCount NEXT FILTER movieCount > 1 @@ -38,7 +38,7 @@ LIMIT 1 | actor | movieCount | |---|---| -| Actor1 | 3 | +| Tom | 3 | Reading the query clause by clause: diff --git a/data-explorer/kusto/query/opencypher-graph-query-language.md b/data-explorer/kusto/query/opencypher-graph-query-language.md index a43c2efff1..1e4ab63b83 100644 --- a/data-explorer/kusto/query/opencypher-graph-query-language.md +++ b/data-explorer/kusto/query/opencypher-graph-query-language.md @@ -26,7 +26,7 @@ Find all actors who acted in a movie. ```openCypher MATCH (n :Person)-[e :ACTED_IN]->(m: Movie) -WHERE m.Title starts with 'A' +WHERE m.Title starts with 'T1' RETURN n.Name as actorName, m.Title as movieTitle ORDER BY actorName desc LIMIT 2 @@ -36,8 +36,8 @@ LIMIT 2 | actorName | movieTitle | |-------------| --------- | -| Actor1 | Movie1 | -| Actor2 | Movie1 | +| Tom | T1 | +| Kevin | T1 | For more openCypher examples, see the [openCypher specification](https://s3.amazonaws.com/artifacts.opencypher.org/openCypher9.pdf). diff --git a/data-explorer/kusto/query/run-graph-query-with-graph-reference.md b/data-explorer/kusto/query/run-graph-query-with-graph-reference.md index fa1ad39a03..28560f3c03 100644 --- a/data-explorer/kusto/query/run-graph-query-with-graph-reference.md +++ b/data-explorer/kusto/query/run-graph-query-with-graph-reference.md @@ -24,27 +24,27 @@ The following example creates a movies graph of relationships between movies and { let Movies = datatable (Title: string, Description: string, Year: int, Label2: dynamic) [ - 'Movie1', 'A movie about space', 1995, dynamic(["Movie","Survival","Adventure","Drama","History"]), - 'Movie2', 'Romantic comedy', 2011, dynamic(["Movie","Comedy","Drama","Romance"]), - 'Movie3', 'War film', 2020, dynamic(["Movie","Drama","History","War"]), + 'T1', 'A movie about space', 1995, dynamic(["Movie","Survival","Adventure","Drama","History"]), + 'T2', 'Romantic comedy', 2011, dynamic(["Movie","Comedy","Drama","Romance"]), + 'T3', 'War film', 2020, dynamic(["Movie","Drama","History","War"]), ] | extend Label = 'Movie'; let People = datatable (Name: string, Born: int, Label2: dynamic) [ - 'Actor1', 1956, dynamic(["Person","Male","BestActorAward"]), - 'Actor2', 1958, dynamic(["Person","Male"]), - 'Actor3', 1954, dynamic(["Person","Male","BestDirectorAward"]), - 'Actor4', 1967, dynamic(["Person","Female","BestActressAward"]), + 'Tom', 1956, dynamic(["Person","Male","BestActorAward"]), + 'Kevin', 1958, dynamic(["Person","Male"]), + 'Ron', 1954, dynamic(["Person","Male","BestDirectorAward"]), + 'Julia', 1967, dynamic(["Person","Female","BestActressAward"]), ] | extend Label = 'Person'; let Actions = datatable(Name: string, Movie: string, Label: string, Label2: dynamic, Role: string) [ - 'Actor1', 'Movie1', 'ACTED_IN', dynamic(["ACTED_IN"]), 'Role1', - 'Actor2', 'Movie1', 'ACTED_IN', dynamic(["ACTED_IN"]), 'Role2', - 'Actor3', 'Movie1', 'DIRECTED', dynamic(["DIRECTED"]), 'Director', - 'Actor1', 'Movie2', 'ACTED_IN', dynamic(["ACTED_IN"]), 'Movie2', - 'Actor1', 'Movie2', 'DIRECTED', dynamic(["DIRECTED"]), 'Director', - 'Actor1', 'Movie3', 'ACTED_IN', dynamic(["ACTED_IN"]), 'Role3', + 'Tom', 'T1', 'ACTED_IN', dynamic(["ACTED_IN"]), 'Role1', + 'Kevin', 'T1', 'ACTED_IN', dynamic(["ACTED_IN"]), 'Role2', + 'Ron', 'T1', 'DIRECTED', dynamic(["DIRECTED"]), 'Director', + 'Tom', 'T2', 'ACTED_IN', dynamic(["ACTED_IN"]), 'Role3', + 'Tom', 'T2', 'DIRECTED', dynamic(["DIRECTED"]), 'Director', + 'Tom', 'T3', 'ACTED_IN', dynamic(["ACTED_IN"]), 'Role4', ]; Actions | make-graph Name --> Movie with People on Name, Movies on Title @@ -79,10 +79,10 @@ Example: { "Query": "datatable(Name:string, Born:int, Label2:dynamic) [ - 'Actor1', 1956, dynamic(['Male', 'BestActorAward']), - 'Actor2', 1958, dynamic(['Male']), - 'Actor3', 1954, dynamic(['Male', 'BestDirectorAward']), - 'Actor4', 1967, dynamic(['Female', 'BestActressAward']), + 'Tom', 1956, dynamic(['Male', 'BestActorAward']), + 'Kevin', 1958, dynamic(['Male']), + 'Ron', 1954, dynamic(['Male', 'BestDirectorAward']), + 'Julia', 1967, dynamic(['Female', 'BestActressAward']), ]", "NodeIdColumn": "Name", "Kind": "AddNodes", @@ -92,9 +92,9 @@ Example: { "Query": "datatable(Title:string, Description:string, Year:int, Label2:dynamic) [ - 'Movie1', 'A movie about space', 1995, dynamic(['Survival', 'Adventure', 'Drama', 'History']), - 'Movie2', 'Romantic comedy', 2011, dynamic(['Comedy', 'Drama', 'Romance']), - 'Movie3', 'War film', 2020, dynamic(['Drama', 'History', 'War']), + 'T1', 'A movie about space', 1995, dynamic(['Survival', 'Adventure', 'Drama', 'History']), + 'T2', 'Romantic comedy', 2011, dynamic(['Comedy', 'Drama', 'Romance']), + 'T3', 'War film', 2020, dynamic(['Drama', 'History', 'War']), ]", "NodeIdColumn": "Title", "Kind": "AddNodes", @@ -104,12 +104,12 @@ Example: { "Query": "datatable(Name:string, Movie:string, Role:string, Label2:string) [ - 'Actor1', 'Movie1', 'Role1', 'ACTED_IN', - 'Actor2', 'Movie1', 'Role2', 'ACTED_IN', - 'Actor1', 'Movie2', 'Movie2', 'ACTED_IN', - 'Actor1', 'Movie3', 'Role3', 'ACTED_IN', - 'Actor3', 'Movie1', 'Director', 'DIRECTED', - 'Actor1', 'Movie2', 'Director', 'DIRECTED', + 'Tom', 'T1', 'Role1', 'ACTED_IN', + 'Kevin', 'T1', 'Role2', 'ACTED_IN', + 'Tom', 'T2', 'Role3', 'ACTED_IN', + 'Tom', 'T3', 'Role4', 'ACTED_IN', + 'Ron', 'T1', 'Director', 'DIRECTED', + 'Tom', 'T2', 'Director', 'DIRECTED', ]", "SourceColumn": "Name", "TargetColumn": "Movie",