F# - 具有多个返回值的密码查询

时间:2014-04-01 11:35:20

标签: f# neo4j neo4jclient

鉴于此查询(来自here

  let pAfollowers =
        client.Cypher
            .Match("n<-[:follows]-e")
            .Where(fun n -> n.Twitter = "tA")
            .Return<Person>("e")
            .Results
            .Select(fun x -> x.Name)

我想调整它并让它返回打包在一起的多个值。 不确定类型的外观:

let pAfollowers =
        client.Cypher
            .Match("n<-[r:follows]-e")
            .Where(fun n -> n.Twitter = "tA")
            .Return<???>("n, r, e")

其次我想知道在CreateUnique之后是否有可能有一个return语句。 我正在尝试调整此查询:

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()

让它返回stdetails

2 个答案:

答案 0 :(得分:3)

好的,好消息/坏消息 - 尽管在实践中,好的事情是坏的:(

好先:

可以在CreateUnique之后返回,例如:

.CreateUnique("s-[:Knows {knowsData}]-t")
.WithParam("knowsData", details)
.Returns<???>( "s,t" )
.Results;

坏消息:

坏消息是你可能无法在F#中执行此操作。 Neo4jClient要求您使用对象初始值设定项或匿名类型来转换数据,因此您可以尝试以下操作:

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

F#编译器根本没有 no 问题。但是,Neo4jClient将使用以下消息抛出Argument异常:

  

表达式必须构造为对象初始值设定项(例如:n =&gt; new MyResultType {Foo = n.Bar}),匿名类型初始值设定项(例如:n =&gt; new {Foo = n。 Bar}),方法调用(例如:n =&gt; n.Count())或成员访问器(例如:n =&gt; n.As()。Bar)。您不能提供代码块(例如:n =&gt; {var a = n + 1;返回a;})或使用带参数的构造函数(例如:n =&gt; new Foo(n))。

问题是,F#没有有对象初始值设定项,也没有匿名类型,你可以与年龄的F#内容纠缠在一起,而不是像C#那样随处可见无法识别F#初始化。

答案 1 :(得分:1)

我对两者都有好消息。这段代码可以使用元组编译得很好,并且可以与支持F#元组的修改后的Neo4jClient一起使用:https://github.com/n074v41l4bl34u/Neo4jClient解决方案基于: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)

&#39;(e:Cypher.ICypherResultItem)上的类型注释&#39;在 fun 中使用多个参数时可以省略。

然而,当使用单个参数时,这将摆脱丑陋的 createExpression&lt; @Func(...)@&gt;)语法。 有关为何在本页底部查看的详细信息:https://gist.github.com/cskardon/8300420