diff --git a/dotnet-manual/modules/ROOT/pages/data-types.adoc b/dotnet-manual/modules/ROOT/pages/data-types.adoc index df6232f6..2c6a76a7 100644 --- a/dotnet-manual/modules/ROOT/pages/data-types.adoc +++ b/dotnet-manual/modules/ROOT/pages/data-types.adoc @@ -114,255 +114,180 @@ Console.WriteLine(result.Result[0].Get("p").Get("location")); |=== -=== `NodeValue` +=== `INode` Represents a node in a graph. -.Essential methods on node objects +.Essential members on node objects [cols="1m,2"] |=== -|Method |Return +|Property/Method |Return -|.labels() +|.Labels |Node labels, as a list. -|.asMap() +|.Properties |Node properties, as a map. -|.get("") -|Value for the given property. +|.Get("") +|Value for the given property, casted to `type`. -|.elementId() -|String identifier for the relationship. +|.ElementId() +|String identifier for the node. This should be used with care, as no guarantees are given about the mapping between id values and elements outside the scope of a single transaction. In other words, using an `elementId` to `MATCH` an element across different transactions is risky. |=== .Retrieve a node and display its details -[source, java] +[source, csharp] ---- -package demo; - -import java.util.Map; - -import org.neo4j.driver.AuthTokens; -import org.neo4j.driver.Driver; -import org.neo4j.driver.GraphDatabase; -import org.neo4j.driver.QueryConfig; - -public class App { - - public static void main(String... args) { - final String dbUri = ""; - final String dbUser = ""; - final String dbPassword = ""; - - try (var driver = GraphDatabase.driver(dbUri, AuthTokens.basic(dbUser, dbPassword))) { - driver.verifyConnectivity(); - - // Get a node from the database - var result = driver.executableQuery("MERGE (p:Person:Actor {name: $name, age: 59}) RETURN p") - .withParameters(Map.of("name", "Alice")) - .withConfig(QueryConfig.builder().withDatabase("neo4j").build()) - .execute(); - - // Extract node from result - var nodeVal = result.records().get(0).get("p"); - var node = nodeVal.asNode(); // .asNode() -> type org.neo4j.driver.types.Node - - System.out.printf("Labels: %s %n", node.labels()); - System.out.printf("Properties: %s %n", node.asMap()); - System.out.printf("Name property: %s %n", node.get("name")); - System.out.printf("Element ID: %s %n", node.elementId()); - /* - Labels: [Person, Actor] - Properties: {name=Alice, age=59} - Name property: "Alice" - Element ID: 4:549a0567-2015-4bb6-a40c-8536bf7227b0:5 - */ - } - } -} +var result = await driver.ExecutableQuery("MERGE (p:Person:Actor {name: $name, age: $age}) RETURN p") + .WithParameters(new { name = "Alice", age = 59 }) + .WithConfig(new QueryConfig(database: "neo4j")) + .ExecuteAsync(); + +var node = result.Result[0].Get("p"); +Console.WriteLine("Labels: {0}", string.Join(", ", node.Labels)); +Console.WriteLine("Properties: {0}", string.Join(", ", node.Properties)); +Console.WriteLine("Name property: {0}", node.Get("name")); +/* +Labels: Person, Actor +Properties: [name, Alice], [age, 59] +Name property: Alice +*/ ---- -For full documentation, see link:https://neo4j.com/docs/api/java-driver/current/org.neo4j.driver/org/neo4j/driver/internal/value/NodeValue.html[API documentation -> NodeValue]. +For full documentation, see link:https://neo4j.com/docs/api/dotnet-driver/current/api/Neo4j.Driver.INode.html[API documentation -> INode]. -=== `RelationshipValue` +=== `IRelationship` Represents a relationship in a graph. -.Essential methods on relationsip objects +.Essential members on relationsip objects [cols="1m,2"] |=== -|Method |Return +|Property/Method |Return -|.type() +|.Type |Relationship type. -|.asMap() +|.Properties |Relationship properties, as a map. -|.get("") -|Value for the given property. +|.Get("") +|Value for the given property, casted to `type`. -|.startNodeElementId() +|.StartNodeElementId |`elementId` of starting node. -|.endNodeElementId() +|.EndNodeElementId | `elementId` of ending node. -|.elementId() +|.ElementId |String identifier for the relationship. This should be used with care, as no guarantees are given about the mapping between id values and elements outside the scope of a single transaction. In other words, using an `elementId` to `MATCH` an element across different transactions is risky. |=== .Retrieve a relationship and display its details -[source, java] +[source, csharp] ---- -package demo; - -import java.util.Map; - -import org.neo4j.driver.AuthTokens; -import org.neo4j.driver.Driver; -import org.neo4j.driver.GraphDatabase; -import org.neo4j.driver.QueryConfig; - -public class App { - - public static void main(String... args) { - final String dbUri = ""; - final String dbUser = ""; - final String dbPassword = ""; - - try (var driver = GraphDatabase.driver(dbUri, AuthTokens.basic(dbUser, dbPassword))) { - driver.verifyConnectivity(); - - // Get a relationship from the database - var result = driver.executableQuery(""" - MERGE (p:Person {name: $name}) - MERGE (p)-[r:KNOWS {status: $status, since: date()}]->(friend:Person {name: $friendName}) - RETURN r AS friendship - """) - .withParameters(Map.of("name", "Alice", "status", "BFF", "friendName", "Bob")) - .withConfig(QueryConfig.builder().withDatabase("neo4j").build()) - .execute(); - - // Extract relationship from result - var relationshipVal = result.records().get(0).get("friendship"); - var relationship = relationshipVal.asRelationship(); // .asRelationship() -> type org.neo4j.driver.types.Relationship - - System.out.printf("Type: %s %n", relationship.type()); - System.out.printf("Properties: %s %n", relationship.asMap()); - System.out.printf("Status property: %s %n", relationship.get("status")); - System.out.printf("Start node: %s %n", relationship.startNodeElementId()); - System.out.printf("End node: %s %n", relationship.endNodeElementId()); - System.out.printf("Element ID: %s %n", relationship.elementId()); - /* - Type: KNOWS - Properties: {since=2024-01-12, status=BFF} - Status property: "BFF" - Start node: 4:549a0567-2015-4bb6-a40c-8536bf7227b0:0 - End node: 4:549a0567-2015-4bb6-a40c-8536bf7227b0:6 - Element ID: 5:549a0567-2015-4bb6-a40c-8536bf7227b0:1 - */ - } - } -} +var result = await driver.ExecutableQuery(@" + MERGE (p:Person {name: $name}) + MERGE (friend:Person {name: $friendName}) + MERGE (p)-[r:KNOWS {status: $status, since: date()}]->(friend) + RETURN r AS friendship + ") + .WithParameters(new { name = "Alice", friendName = "Bob", status = "BFF" }) + .WithConfig(new QueryConfig(database: "neo4j")) + .ExecuteAsync(); + +var relationship = result.Result[0].Get("friendship"); +Console.WriteLine($"Type: {relationship.Type}"); +Console.WriteLine("Properties: {0}", string.Join(", ", relationship.Properties)); +Console.WriteLine("Status property: {0}", relationship.Get("status")); +/* +Type: KNOWS +Properties: [since, 2024-12-22], [status, BFF] +Status property: BFF +*/ ---- -For full documentation, see link:https://neo4j.com/docs/api/java-driver/current/org.neo4j.driver/org/neo4j/driver/internal/value/RelationshipValue.html[API documentation -> RelationshipValue]. +For full documentation, see link:https://neo4j.com/docs/api/dotnet-driver/current/api/Neo4j.Driver.IRelationship.html[API documentation -> IRelationship]. -=== `PathValue` +=== `IPath` Represents a path in a graph. -The driver breaks paths into (iterable) _segments_, consisting of a start node, one relationship, and an end node. -Segments entities may be retrieved, in order, via the methods `.start()`, `.relationship()`, and `.end()`. - -.Retrieve a path and _walk_ it, listing nodes and relationship -[source, java] +.Retrieve a path and _walk_ it +[source, csharp] ---- -package demo; - -import java.util.Map; - -import org.neo4j.driver.AuthTokens; -import org.neo4j.driver.Driver; -import org.neo4j.driver.GraphDatabase; -import org.neo4j.driver.types.Path; -import org.neo4j.driver.QueryConfig; - -public class App { - - public static void main(String... args) { - final String dbUri = ""; - final String dbUser = ""; - final String dbPassword = ""; - - try (var driver = GraphDatabase.driver(dbUri, AuthTokens.basic(dbUser, dbPassword))) { - driver.verifyConnectivity(); - - // Create some :Person nodes linked by :KNOWS relationships - addFriend(driver, "Alice", "BFF", "Bob"); - addFriend(driver, "Bob", "Fiends", "Sofia"); - addFriend(driver, "Sofia", "Acquaintances", "Sofia"); - - // Follow :KNOWS relationships outgoing from Alice three times, return as path - var result = driver.executableQuery(""" - MATCH path=(:Person {name: $name})-[:KNOWS*3]->(:Person) - RETURN path AS friendshipChain - """) - .withParameters(Map.of("name", "Alice")) - .withConfig(QueryConfig.builder().withDatabase("neo4j").build()) - .execute(); - - // Extract path from result - var pathVal = result.records().get(0).get("friendshipChain"); - var path = pathVal.asPath(); // .asPath() -> type org.neo4j.driver.types.Path - - System.out.println("-- Path breakdown --"); - for (Path.Segment segment : path) { - System.out.printf( - "%s is friends with %s (%s).%n", - segment.start().get("name").asString(), - segment.end().get("name").asString(), - segment.relationship().get("status").asString()); - } - /* - -- Path breakdown -- - Alice is friends with Bob (BFF). - Bob is friends with Sofia (Fiends). - Sofia is friends with Sofia (Acquaintances). - */ - } - } - - public static void addFriend(Driver driver, String name, String status, String friendName) { - driver.executableQuery(""" - MERGE (p:Person {name: $name}) - MERGE (p)-[r:KNOWS {status: $status, since: date()}]->(friend:Person {name: $friendName}) - """) - .withParameters(Map.of("name", name, "status", status, "friendName", friendName)) - .withConfig(QueryConfig.builder().withDatabase("neo4j").build()) - .execute(); - } +using Neo4j.Driver; + +const string dbUri = ""; +const string dbUser = ""; +const string dbPassword = ""; + +await using var driver = GraphDatabase.Driver(dbUri, AuthTokens.Basic(dbUser, dbPassword)); +await driver.VerifyConnectivityAsync(); + +// Create some :Person nodes linked by :KNOWS relationships +await addFriend(driver, "Alice", "BFF", "Bob"); +await addFriend(driver, "Bob", "Fiends", "Sofia"); +await addFriend(driver, "Sofia", "Acquaintances", "Sofia"); + +// Follow :KNOWS relationships outgoing from Alice three times, return as path +var result = await driver.ExecutableQuery(@" + MATCH path=(:Person {name: $name})-[:KNOWS*3]->(:Person) + RETURN path AS friendshipChain + ") + .WithParameters(new { name = "Alice", friendName = "Bob", status = "BFF" }) + .WithConfig(new QueryConfig(database: "neo4j")) + .ExecuteAsync(); + +// Extract path from result +var path = result.Result[0].Get("friendshipChain"); + +Console.WriteLine("-- Path breakdown --"); +for (var i=0; i("name"), + path.Nodes[i+1].Get("name"), + path.Relationships[i].Get("status") + ); +} +/* +-- Path breakdown -- +Alice is friends with Bob (BFF). +Bob is friends with Sofia (Fiends). +Sofia is friends with Sofia (Acquaintances). +*/ + +async Task addFriend(IDriver driver, string name, string status, string friendName) { + await driver.ExecutableQuery(@" + MERGE (p:Person {name: $name}) + MERGE (friend:Person {name: $friendName}) + MERGE (p)-[r:KNOWS {status: $status, since: date()}]->(friend) + ") + .WithParameters(new { name = name, status = status, friendName = friendName }) + .WithConfig(new QueryConfig(database: "neo4j")) + .ExecuteAsync(); } ---- -For full documentation, see link:https://neo4j.com/docs/api/java-driver/current/org.neo4j.driver/org/neo4j/driver/internal/value/PathValue.html[API documentation -> PathValue]. +For full documentation, see link:https://neo4j.com/docs/api/dotnet-driver/current/api/Neo4j.Driver.IPath.html[API documentation -> IPath]. == Exceptions -The driver can raise a number of different exceptions, see link:https://neo4j.com/docs/api/java-driver/current/org.neo4j.driver/org/neo4j/driver/exceptions/package-summary.html[API documentation -> Exceptions]. +The driver can raise a number of different exceptions, see link:https://neo4j.com/docs/api/dotnet-driver/current/api/Neo4j.Driver.Neo4jException.html[API documentation -> Neo4jException]. Exception objects are GQL-compliant. + For a list of errors the server can return, see link:{neo4j-docs-base-uri}/status-codes/{page-version}[Status codes]. Some server errors are marked as safe to retry without need to alter the original request. +Those exceptions have a `true` value for the `.IsRetriable` property. Examples of such errors are deadlocks, memory issues, or connectivity issues. -Driver's exceptions implementing link:https://neo4j.com/docs/api/java-driver/current/org.neo4j.driver/org/neo4j/driver/exceptions/RetryableException.html[`RetryableException`] are such that a further attempt at the operation that caused it might be successful. This is particular useful when running queries in xref:transactions#explicit-transactions[explicit transactions], to know if a failed query is worth re-running.