Question

The Neop4jClient cypher wiki (https://github.com/Readify/Neo4jClient/wiki/cypher) contains an example of using lambda expressions to return multiple projections...

var query = client
.Cypher
.Start(new { root = client.RootNode })
.Match("root-[:HAS_BOOK]->book-[:PUBLISHED_BY]->publisher")
.Return((book, publisher) => new {
    Book = book.As<Book>(),
    Publisher = publisher.As<Publisher>(),
});

So the query will return details of both book nodes and publisher nodes. But I want to do something slightly different. I want to combine the contents of a single node type with a property of the matched path. Lets say I have Person nodes with a property 'name', and a class defined so,,,

public class descendant
{
    public string name { get; set; }
    public int depth { get; set; }
}

A cypher query like this will return what I want, which is all descendants of a given node with the depth of the relationship...

match p=(n:Person)<-[*]-(child:Person) 
where n.name='George' 
return distinct child.name as name, length(p) as depth

If I try a Neo4jClient query like this...

var query =
     _graphClient.Cypher
          .Match("p=(n:Person)<-[*]-(child:Person)")
          .Where("n.name='George'")
          .Return<descendant>("child.name,  length(p)") ;

I get an error that the syntax is obsolete, but I can't figure out how should I project the cypher results onto my C# POCO. Any ideas anyone?

Was it helpful?

Solution

The query should look like this:

var query = 
    _graphClient.Cypher
        .Match("p=(n:Person)<-[*]-(child:Person)")
        .Where((Person n) => n.name == "George")
        .Return((n,p) => new descendant
        {
            name = n.As<Person>().Name,
            depth = p.Length()
        });

The Return statement should have the 2 parameters you care about (in this case n and p) and project them via the lambda syntax (=>) to create a new descendant instance. The main point this differs from the example, is that the example creates a new anonymous type, whereas you want to create a concrete type.

We then use the property initializer (code inside the { } braces) to set the name and depth, using the As<> and Length extension methods to get the values you want.

As a side note, I've also changed the Where clause to use parameters, you should always do this if you can, it will make your queries both faster and safer.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top