Skip to content

5.8.0

Compare
Choose a tag to compare
@RichardIrons-neo4j RichardIrons-neo4j released this 28 Apr 12:17
· 108 commits to 5.0 since this release
815281a

⭐ New Features

  • The ExecuteQuery API has now been moved out of preview. This provides a much simpler way to execute queries directly at the driver level, with sessions, transactions and bookmarks handled automatically.
Examples
var queryOp = await driver
    .ExecutableQuery("MATCH (person:Person) RETURN person")
    .ExecuteAsync();

Query Execution Result

The result of executing a query in the way shown above is an EagerResult<T>, where T is the type of data returned from the query. In the simplest case, this will be an IReadOnlyList<IRecord>, which is a fully materialized list of the records returned by the query. Other types of results can be used by using the fluent API exposed by the IExecutableQuery type, for example:

var queryOp = await driver
    .ExecutableQuery("MATCH (person:Person) RETURN person")
    .WithMap(r => r["person"].As<INode>()["name"].As<string>())
    .WithFilter(s => s.StartsWith("A"))
    .ExecuteAsync();

With this method, the return type will be EagerResult<IReadonlyList<string>>. Multiple .WithMap and .WithFilter calls may be chained together. Note that filtering is performed locally here so it should not be used in place of doing filtering on the server.

There is also a .WithReduce method, to be used as follows:

var queryOp = await driver
    .ExecutableQuery("MATCH (person:Person) RETURN person")
    .WithMap(r => r["person"].As<INode>()["age"].As<int>())
    .WithReduce(() => 0, (r, n) => r + n)
    .ExecuteAsync();

This will result in an EagerResult<int>, with the Result property containing the sum of all the ages.

Custom processing of the record stream can be done by using the .WithStreamProcessor method:

var queryOp = await driver
    .ExecutableQuery("MATCH (person:Person) RETURN person")
    .WithStreamProcessor(
        async stream =>
        {
            double total = 0;
            int count = 0;

            await foreach(var record in stream)
            {
                var age = record["person"].As<INode>()["age"].As<double>();
                total += age;
                count++;
            }

            return total / count;
        })
    .ExecuteAsync();

Here we simply supply a delegate, which will be called, passing a parameter of type IAsyncEnumerable<IRecord>. The value returned from this delegate will be an EagerResult<double>, with the Result property containing the average age.

Parameters can also be specified using the fluent interface, as follows.

var paramQuery = await driver
    .ExecutableQuery("MATCH (p:Person) WHERE p.name = $name RETURN p")
    .WithParameters(new { name = "Tom Hanks" })
    .WithMap(r => r["p"].As<INode>()["name"].As<string>())
    .ExecuteAsync();