Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update documentation with new patterns syntax #332

Merged
merged 2 commits into from
May 2, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/modules/ROOT/pages/functions.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ In these cases, you can directly call the provided functions to generate the equ

[source, javascript]
----
const movie = new Cypher.Node({labels: ["Movie"]});
const movie = new Cypher.Node();

Cypher.coalesce(movie.property("title"), new Cypher.Param("The Matrix"));
----
Expand Down
16 changes: 11 additions & 5 deletions docs/modules/ROOT/pages/getting-started/connecting-to-neo4j.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,14 @@ For instance, this query:

[source, javascript]
----
const movie = new Cypher.Node({ labels: ["Movie"] });
const query = new Cypher.Match(movie).return([movie.property("title"), "title"]);
const movie = new Cypher.Node();
const query = new Cypher.Match(new Cypher.Pattern(movie, { labels: ["Movie"] })).return([
movie.property("title"),
"title",
]);
----

Will translate to:
This will translate to:

[source, cypher]
----
Expand Down Expand Up @@ -110,8 +113,11 @@ import neo4j from "neo4j-driver";

const driver = neo4j.driver("neo4j://localhost", neo4j.auth.basic("neo4j", "password"));

const movie = new Cypher.Node({ labels: ["Movie"] });
const query = new Cypher.Match(movie).return([movie.property("title"), "title"]);
const movie = new Cypher.Node();
const query = new Cypher.Match(new Cypher.Pattern(movie, { labels: ["Movie"] })).return([
movie.property("title"),
"title",
]);

const { cypher, params } = query.build();
const { records } = await driver.executeQuery(cypher, params);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ Here is how you should proceed:
+
[source, javascript]
----
const clause = new Cypher.Match(movieNode)
const movieNode = new Cypher.Node()
const clause = new Cypher.Match(new Cypher.Pattern(movieNode, { labels: ["Movie"] }))
.where()
.return(movieNode);
----
Expand Down Expand Up @@ -61,7 +62,7 @@ Though it is possible to inject the string value into the query, it is good prac
+
[source, javascript]
----
const clause = new Cypher.Match(movieNode)
const clause = new Cypher.Match(new Cypher.Pattern(movieNode, { labels: ["Movie"] }))
.where(Cypher.eq(movieNode.property("title"), new Cypher.Param("The Matrix")))
.return(movieNode);
----
Expand Down Expand Up @@ -207,7 +208,7 @@ const titleProp = movieNode.property("title");
const yearProp = movieNode.property("released");
const taglineProp = movieNode.property("tagline");

const clause = new Cypher.Match(movieNode)
const clause = new Cypher.Match(new Cypher.Pattern(movieNode, { labels: ["Movie"] }))
.where(Cypher.eq(titleProp, new Cypher.Param("The Matrix")))
.and(Cypher.lt(yearProp, new Cypher.Param(2000)))
.return(titleProp, taglineProp, yearProp);
Expand Down
26 changes: 16 additions & 10 deletions docs/modules/ROOT/pages/getting-started/querying.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,22 @@ RETURN m
+
[source, javascript]
----
const movieNode = new Cypher.Node({
labels: ["Movie"]
});
const movieNode = new Cypher.Node();
----

. Create a `MATCH` clause and pass the node variable as an argument:
. Create the pattern to be matched against with `Cypher.Pattern`:
+
[source, javascript]
----
const clause = new Cypher.Match(movieNode);
const matchPattern = new Cypher.Pattern(movieNode, { labels: ["Movie"] });
----


. Create a `MATCH` clause and pass the pattern as an argument:
+
[source, javascript]
----
const clause = new Cypher.Match(matchPattern);
----

. To `RETURN` the Node variables, use the `.return` method in the `MATCH` clause:
Expand All @@ -39,7 +45,7 @@ clause.return(movieNode);
+
[source, javascript]
----
const clause = new Cypher.Match(movieNode).return(movieNode);
const clause = new Cypher.Match(matchPattern).return(movieNode);
----

. After the query is ready, it is time to build it.
Expand All @@ -60,11 +66,11 @@ Altogether, your script should look like this:
----
import Cypher from "@neo4j/cypher-builder";

const movieNode = new Cypher.Node({
labels: ["Movie"]
});
const movieNode = new Cypher.Node();

const matchPattern = new Cypher.Pattern(movieNode, { labels: ["Movie"] });

const clause = new Cypher.Match(movieNode).return(movieNode);
const clause = new Cypher.Match(matchPattern).return(movieNode);

const { cypher } = clause.build();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,20 +34,16 @@ For more complex `MATCH` statements, like the one in this tutorial, you should d

== Pattern creation

These are the steps you should follow to define a pattern:
These are the steps you should follow to define a more complex pattern:

. Define the elements of the pattern.
Relationships, just like nodes, are variables that can be created and reused across your query:
+
[source, javascript]
----
const actedIn = new Cypher.Relationship({
type: "ACTED_IN",
});
const actedIn = new Cypher.Relationship();

const personNode = new Cypher.Node({
labels: ["Person"],
});
const personNode = new Cypher.Node();
----
+
So far, the relationship is not connected to the nodes.
Expand All @@ -57,7 +53,9 @@ This is because here you are creating a variable to hold the relationship matche
+
[source, javascript]
----
const pattern = new Cypher.Pattern(movieNode).related(actedIn).to(personNode);
const pattern = new Cypher.Pattern(movieNode, { labels: ["Movie"] })
.related(actedIn, { type: "ACTED_IN" })
.to(personNode, { labels: ["Person"] });
----
+
Note that, in Cypher Builder, patterns work similarly to Cypher, with each element of the chain being either a relationship or a node.
Expand Down Expand Up @@ -91,11 +89,13 @@ For more information about creating patterns, refer to xref:patterns.adoc[Patter
Despite changing the `MATCH` target in the previous steps, all the filters and relationships featured in the query are still pointing towards the correct variable: `this0`.
However, the pattern is incorrect -- instead of returning a `Person` acting in a `Movie`, there is a `Movie` acting on a `Person`.

To change that, add `.withDirection("left")` to the pattern:
To change that, add `direction: "left"` to the `related` options:

[source, javascript]
----
const pattern = new Cypher.Pattern(movieNode).related(actedIn).withDirection("left").to(people);
const pattern = new Cypher.Pattern(movieNode, { labels: ["Movie"] })
.related(actedIn, { type: "ACTED_IN", direction: "left" })
.to(people, { labels: ["Person"] });
----

Any aspect of the pattern itself (cardinality, direction and properties) can be changed in the pattern declaration with the methods of each element in the "chain".
Expand Down Expand Up @@ -130,10 +130,10 @@ This advanced filter is composed of 3 basic comparisons:
* `m.title CONTAINS "Matrix"`
* `m.released < 2000`

These comparisons use the logic operations `AND`, `NOT`, and `OR`, respectivelly.
These comparisons use the logic operations `AND`, `NOT`, and `OR`, respectively.

Still, as advanced queries grow, they can start to hinder maintenance.
To avoid this scenario, it is advisable to split the query into more basic comparisons and compose it afterwards.
To avoid this scenario, it is advisable to split the query into more basic comparisons and compose it afterward.

The process is similar to how you would perform with nodes and patterns:

Expand Down Expand Up @@ -217,19 +217,13 @@ After going through all the steps previously described, your script should look
----
import Cypher from "@neo4j/cypher-builder";

const movieNode = new Cypher.Node({
labels: ["Movie"],
});
const movieNode = new Cypher.Node();
const actedIn = new Cypher.Relationship();
const personNode = new Cypher.Node();

const actedIn = new Cypher.Relationship({
type: "ACTED_IN",
});

const personNode = new Cypher.Node({
labels: ["Person"],
});

const pattern = new Cypher.Pattern(movieNode).related(actedIn).withDirection("left").to(personNode);
const pattern = new Cypher.Pattern(movieNode, { labels: ["Movie"] })
.related(actedIn, { type: "ACTED_IN", direction: "left" })
.to(personNode, { labels: ["Person"] });

const titleProp = movieNode.property("title");
const yearProp = movieNode.property("released");
Expand All @@ -243,8 +237,7 @@ const releasedBefore2000 = Cypher.lt(yearProp, new Cypher.Param(2000));
const clause = new Cypher.Match(pattern)
.where(Cypher.and(isKeanu, Cypher.or(Cypher.not(titleContainsMatrix), releasedBefore2000)))
.return(titleProp, taglineProp, yearProp, [rolesProperty, "actingRoles"]);

const { cypher, params } = clause.build();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
const { cypher, params } = clause.build();

console.log(cypher);
console.log(params);
----
Expand Down
20 changes: 10 additions & 10 deletions docs/modules/ROOT/pages/how-to/customize-cypher.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ For example, this query:

[source, javascript]
----
const match1=new Cypher.Match(new Cypher.Node({ labels: ["Movie"] }))
const match2=new Cypher.Match(new Cypher.Node({ labels: ["Person"] }))
const match1=new Cypher.Match(new Cypher.Pattern(new Cypher.Node(), { labels: ["Movie"] }))
const match2=new Cypher.Match(new Cypher.Pattern(new Cypher.Node(), { labels: ["Person"] }))

const cypher=`
${match1.build()}
Expand All @@ -47,8 +47,8 @@ Generates the following Cypher:

[source, cypher]
----
MATCH(this0:Movie)
MATCH(this0:Person)
MATCH(:Movie)
MATCH(:Person)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You passed the Node in the Pattern above so I believe here it will be printed as this0:Movie and this1:Person

----

In this query, the variable `this0` is used for both `MATCH` statements, thus causing variable name collision.
Expand Down Expand Up @@ -112,8 +112,8 @@ For example, this query:

[source, javascript]
----
const movie = new Cypher.Node({ labels: ["Movie"] });
const matchQuery = new Cypher.Match(movie).where(movie, { name: new Cypher.NamedParam("myParam") }).return(movie);
const movie = new Cypher.Node();
const matchQuery = new Cypher.Match(movie, { labels: ["Movie"]}).where(movie, { name: new Cypher.NamedParam("myParam") }).return(movie);
----

Generates the following query:
Expand All @@ -130,8 +130,8 @@ To generate the parameter, pass a value in the same way as normal parameters:

[source, javascript]
----
const movie = new Cypher.Node({ labels: ["Movie"] });
const matchQuery = new Cypher.Match(movie).where(movie, { name: new Cypher.NamedParam("myParam", "Keanu Reeves") }).return(movie);
const movie = new Cypher.Node();
const matchQuery = new Cypher.Match({movie, labels: ["Movie"] }).where(movie, { name: new Cypher.NamedParam("myParam", "Keanu Reeves") }).return(movie);
----

The resulting parameter is:
Expand Down Expand Up @@ -302,8 +302,8 @@ However, a custom `Raw` is being injected as part of the `WHERE` subclause:

[source, javascript]
----
const movie = new Cypher.Node({ labels: ["Movie"] });
const match = new Cypher.Match(movie)
const movie = new Cypher.Node();
const match = new Cypher.Match(movie, { labels: ["Movie"] })
.where(
new Cypher.Raw((env) => {
const movieStr = env.compile(movie);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,13 +36,13 @@ Type predicate expressions can be used in a `WHERE` statement, for example:

[source, javascript]
----
const movie = new Cypher.Node({ labels: ["Movie"] });
const matchClause = new Cypher.Match(movie).where(Cypher.isType(movie.property("title"), Cypher.TYPE.STRING)).return(movie);
const node = new Cypher.Node();
const matchClause = new Cypher.Match(node).where(Cypher.isType(node.property("title"), Cypher.TYPE.STRING)).return(node);
----

[source, cypher]
----
MATCH (this0:Movie)
MATCH (this0)
WHERE this0.title IS :: STRING
RETURN this0
----
Expand Down
Loading