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

Posted

技术标签:

【中文标题】F# - 具有多个返回值的密码查询【英文标题】:F# - cypher query with multiple return values 【发布时间】:2014-04-01 11:35:19 【问题描述】:

鉴于此查询(来自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 之后是否可以有一个返回语句。 我正在尝试调整此查询:

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

【问题讨论】:

【参考方案1】:

好吧,好消息/坏消息 - 虽然在实践中好与坏:(

先好:

可以在 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# 编译器完全没有 问题。但是,Neo4jClient 将引发 Argument 异常并显示以下消息:

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

问题在于,F# 没有 有对象初始化器,也没有匿名类型,你可以为 ages 使用 F# 的东西,却一无所获,就像 C#无法识别 F# 初始化。

【讨论】:

"F# 没有对象初始化器" 如果我​​理解你的意思是正确的,那么它确实有。请参阅“在初始化时为属性赋值”here。 不得不说我很困惑。 在 F# 3.0 中,我们添加了 CLIMutableAttribute。如果将此属性附加到 F# 记录类型 ... ,则 F# 编译器会为该类型生成的 IL 发出默认构造函数和属性设置器(尽管这些功能不会暴露给 F# 代码) @987654322 @ @ildjarn & NoIdeaHowToFixThis - 我的意思是就 C# 代码(在 neo4jclient 库中)而言 - 这不是对象初始化程序(我真的不是 F# 开发人员 - 非常高兴(实际上很高兴)被证明是错误的)。问题在于 C# 库如何读取代码。它在功能上是等价的,但在反射类型时相同 - 这是客户端所做的。 好的,谢谢。我懂了。我找不到解决方法。这个问题对我来说是一个表演终结者。想知道我是否应该关闭这个问题并提出一个关于在类似情况下使用LeafExpressionConverter.QuotationToLambdaExpression 的更通用的问题。 我不能再添加更多了 - 我已经尝试过使用结构体、F# 的初始化程序等,但我最后没有高兴 - 正如我所说 - 我不擅长 F#,所以你可以坚持看看 F# 大师是否可以提供帮助 - 但请记住 - 如果您提出在 neo4jclient 中使用它的想法的问题,您需要指定它将被 C# 库使用,这个要点:gist.github.com/cskardon/9935002 应该会有所帮助 - 如果你能得到F# 调用它并返回 true 你应该是好的。【参考方案2】:

我对双方都有一些好消息。此代码将使用元组编译得很好,并且可以与支持 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)

fun 中使用多个参数时,可以省略“(e : Cypher.ICypherResultItem)”上的类型注释。

但是,当使用单个参数时,这摆脱了丑陋的 createExpression ) 语法。 详情请看本页底部:https://gist.github.com/cskardon/8300420

【讨论】:

这个有没有被迁移到master并且在包中可用? 根据github.com/Readify/Neo4jClient/commit/…,它已于 2014 年 5 月 26 日被拉回 master 分支,因此它应该可用。

以上是关于F# - 具有多个返回值的密码查询的主要内容,如果未能解决你的问题,请参考以下文章

使用两个可以返回多个值的子查询的 SQL 之间的语句

聚合具有相同字段值的查询项

如何在 neo4j .net 客户端中使用密码查询返回两个集合

如何正确查询firestore数据库?

使用名为查询的数据 jpa 返回具有不同列值的行

访问具有多个值的文本框进行查询