Search code examples
c#cypherneo4jclient

Cypher query with select first item from collect in neo4jclient


I have the following code but I don't know how to do it in C# using the graphclient. It's the RETURN nodes[0] that confuses me.

What it does is that it will return all nodes and their properties with a distinct value of name.

PROFILE MATCH (t:Node { Mapped: true}) 
WITH t.name as t, collect(t) AS nodes
RETURN nodes[0]

Current implementation required me to get all and then use LINQ to get the distinct but this is slower:

 var res = graphClient.Cypher
                    .Match(match)
                    .Return(t => new
                    {
                        N = Return.As<string>("t.name")                       
                        LA = Return.As<double>("t.lat"),
                        LO = Return.As<double>("t.lon")
                    })
                    .OrderBy("t.name")
                    .Results;

//TODO: THE DISTINT NEEDS TO BE IN THE QUERY INSTEAD OF AFTER RESULT.
return res.Where(p => p.N != null).GroupBy(p => p.N).Select(grp => grp.FirstOrDefault());

Solution

  • You're probably going to want a proper result class instead of trying an anonymous type for this, so if you have this:

    public class Location{
        [JsonProperty("name")]
        public string Name {get;set;}
        [JsonProperty("lat")]
        public double Lat { get; set; }
        [JsonProperty("lon")]
        public double Lon { get; set; }
    }
    

    You can then write the query as:

    var query = client.Cypher
        .Match("(t:Node {Mapped: true})")
        .With("t.name AS t, collect(t) AS nodes")
        .Return(() => Return.As<Location>("nodes[0]"));
    

    Which if you look at:

    query.Query.DebugQueryText
    

    You should see:

    MATCH (t:Node {Mapped: true})
    WITH collect(t) AS nodes
    RETURN nodes[0]