F# - cypher query with multiple return values
f#, neo4j, neo4jclient
Solution
OK, good news / bad news - though in practice the good is tempered with bad :(
Good first:
You can return after a CreateUnique, something like:
.CreateUnique("s-[:Knows {knowsData}]-t")
.WithParam("knowsData", details)
.Returns<???>( "s,t" )
.Results;
Bad news:
The bad news is that you probably can't do it in F#. `Neo4jClient` requires you to use either object initializers, or anonymous types to cast the data, so you could try something like:
type FollowingResults = { Follower : Person; Followed : Person;}
let createExpression quotationExpression = LeafExpressionConverter.QuotationToLambdaExpression quotationExpression
let pAfollowers =
client.Cypher
.Match("n<-[:follows]-e")
.Where(fun n -> n.Twitter = "tA")
.Return(createExpression <@ Func<ICypherResultItem, ICypherResultItem, FollowingResults>(fun (e : Cypher.ICypherResultItem) (n : Cypher.ICypherResultItem) -> {Follower = e.As<Person>(); Followed = n.As<Person>()}) @>)
.Results
.Select(fun x -> x)
for follower in pAfollowers do
printfn "%s followed %s" follower.Follower.Name follower.Followed.Name
For which the F# compiler will have no problems at all. However, `Neo4jClient` will throw an Argument exception with the following message:
The expression must be constructed as either an object initializer (for example: n => new MyResultType { Foo = n.Bar }), an anonymous type initializer (for example: n => new { Foo = n.Bar }), a method call (for example: n => n.Count()), or a member accessor (for example: n => n.As().Bar). You cannot supply blocks of code (for example: n => { var a = n + 1; return a; }) or use constructors with arguments (for example: n => new Foo(n)).
The problem being, F# doesn't have object initializers, nor anonymous types, you can wrangle with the F# stuff for ages and not get anywhere, as the C# doesn't recognize the F# initialization.
Problem
Given this query (from here) ``` let pAfollowers = client.Cypher .Match("n<-[:follows]-e") .Where(fun n -> n.Twitter = "tA") .Return<Person>("e") .Results .Select(fun x -> x.Name) ``` I would like to tweak it and have it return multiple values packaged together. Not sure about how the type should look: ``` let pAfollowers = client.Cypher .Match("n<-[r:follows]-e") .Where(fun n -> n.Twitter = "tA") .Return<???>("n, r, e") ``` Secondly I was wondering if it is possible to have a return statement after a `CreateUnique`. I am trying to tweak this query: ``` let knows target (details : Knows) source = client.Cypher .Match("(s:Person)", "(t:Person)") .Where(fun s -> s.Twitter = source.Twitter) .AndWhere(fun t -> t.Twitter = target.Twitter) .CreateUnique("s-[:knows {knowsData}]->t") .WithParam("knowsData", details) .ExecuteWithoutResults() ``` to have it return `s`, `t` and the `details`.