F#- consulta de cifrado con valores de retorno mĂșltiples
neo4j neo4jclient (2)
OK, buenas / malas noticias, aunque en la práctica el bien se atenúa con mal :(
Bien primero:
Puedes regresar después de CreateUnique, algo así como:
.CreateUnique("s-[:Knows {knowsData}]-t")
.WithParam("knowsData", details)
.Returns<???>( "s,t" )
.Results;
Malas noticias:
La mala noticia es que probablemente no puedas hacerlo en F #. Neo4jClient
requiere que use ya sea inicializadores de objetos o tipos anónimos para transmitir los datos, por lo que podría intentar algo como:
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
Para lo cual el compilador F # no tendrá ningún problema. Sin embargo, Neo4jClient
lanzará una excepción Argument con el siguiente mensaje:
La expresión debe construirse como un inicializador de objetos (por ejemplo: n => new MyResultType {Foo = n.Bar}), un inicializador de tipo anónimo (por ejemplo: n => new {Foo = n.Bar}), un llamada de método (por ejemplo: n => n.Count ()), o un descriptor de acceso de miembro (por ejemplo: n => n.As (). Bar). No puede suministrar bloques de código (por ejemplo: n => {var a = n + 1; return a;}) o usar constructores con argumentos (por ejemplo: n => new Foo (n)).
El problema es que F # no tiene inicializadores de objetos, ni tipos anónimos, puede discutir con las cosas F # por edades y no llegar a ningún lado, ya que C # no reconoce la inicialización F #.
Dada esta consulta (de aquí )
let pAfollowers =
client.Cypher
.Match("n<-[:follows]-e")
.Where(fun n -> n.Twitter = "tA")
.Return<Person>("e")
.Results
.Select(fun x -> x.Name)
Me gustaría ajustarlo y hacer que devuelva múltiples valores empaquetados juntos. No estoy seguro de cómo debería verse el tipo:
let pAfollowers =
client.Cypher
.Match("n<-[r:follows]-e")
.Where(fun n -> n.Twitter = "tA")
.Return<???>("n, r, e")
En segundo lugar, me preguntaba si es posible tener una declaración de devolución después de CreateUnique
. Estoy tratando de modificar esta consulta:
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()
para que devuelva s
, t
y los details
.
Tengo buenas noticias para ambos. Este código se compilará perfectamente utilizando tuplas y se puede usar con un Neo4jClient modificado que admita F # Tuples: https://github.com/n074v41l4bl34u/Neo4jClient Solution se basa en: 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)
La anotación de tipo en ''(e: Cypher.ICypherResultItem)'' se puede omitir cuando se usan más de un argumento de manera divertida .
Sin embargo, al usar un solo argumento, esto elimina la fea sintaxis createExpression <@ Func (...) @>) . Para detalles sobre por qué mirar en la parte inferior de esta página: https://gist.github.com/cskardon/8300420