Search code examples
neo4jclient

How to execute a filter in the return clause of a cypher query in the .net Neo4jClient


I'm having trouble figuring out how to put a filter in the return clause using the cypher linq Return function in the neo4j client.

I'm trying to do a query like this:

START Parents = node:app_fulltext('name:"City"'),
 MATCH Parents-[?:ChildOf]-Apps 
 WITH collect(Apps.Title) as myapps, collect(Parents.Name) as myparents
 RETURN myapps, filter(x in parents : not x in myapps) as myfilteredparents

I've tried starting with a with clause like this

.With("collect(Apps.Title) as myapps, collect(Parents.Name) as myparents")
.Return("myapps, filter(x in parents : not x in myapps) as myfilteredparents")

but I can't pass in a string to the Return method, and if I try to pass in some sort of filter into the LINQ lambda I get a The return expression that you have provided uses methods other than those defined by ICypherResultItem. error.


Solution

  • Right now, complex return expressions with multiple identities are a bit icky in Neo4jClient. I'm open to ideas about how to support them nicely. The syntax is the hard part.

    This is on the right track:

    .With("myapps, filter(x in parents : not x in myapps) as myfilteredparents")
    .Return("myapps, filter(x in parents : not x in myapps) as myfilteredparents")
    

    However you're applying the filter twice: once in the WITH, then again in the RETURN.

    Use the WITH clause to flatten it to simple identities (myapps, myfilteredparents) then RETURN those.

    This code is untested, and typed straight into the answer window, but kind of what you want:

    .With("myapps, filter(x in parents : not x in myapps) as myfilteredparents")
    .Return((myapps, myfilteredparents) => new
    {
        Apps = myapps.As<IEnumerable<string>>(),
        Parents = myfilteredparents.As<IEnumerable<Node<City>>>()
    })
    

    The With call shapes the data into a simple result set. The Return call describes the structure to deserialize this into.