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
.
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.
I have somewhat good news to both. This code will compile just fine using tuples and can be used with a modified Neo4jClient that supports F# Tuples: https://github.com/n074v41l4bl34u/Neo4jClient Solution is based on: https://fsharppowerpack.codeplex.com/workitem/4572
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)
.Return(fun s t -> s.As<Person>(),t.As<Person>())
let pAfollowers =
client.Cypher
.Match("n<-[:follows]-e")
.Where(fun n -> n.Twitter = "tA")
.Return(fun (e : Cypher.ICypherResultItem) n -> e.As<Person>().Name,n.As<Person>().Name)
The type annotation on '(e : Cypher.ICypherResultItem)' can be omited when using more than one argument in fun.
However, when using a single argument, this gets rid off the ugly createExpression <@ Func(...) @>) syntax. For details on why look on the bottom of this page: https://gist.github.com/cskardon/8300420
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With