How to return COLLECT([role, app]) using Neo4jClient?

自作多情 提交于 2019-12-13 04:41:44

问题


I have the following Cypher which I am struggling to translate into the fluent syntax:

MATCH (u:User)-[:HAS_ROLE]->(r:Role)-[:ROLE_OF]->(a:App) 
RETURN u AS User, COLLECT([r, a]) AS Roles

This is what I have so far, but I can't figure out how to return the COLLECT([r, a]) as Roles. I am using a UserDetails class to enable passing the results to a View.

var results = _graphClient.Cypher
    .Match("(user:User)-[:HAS_ROLE]->(role:Role)-[:ROLE_OF]->(app:App)")
    .Return((user,role,app) => new UserDetails {
        User = user.As<User>(),
        Roles = ???
    })
    .OrderBy("user.Username")
    .Results;

I first tried a dictionary, but Neo4jClient only allows returning as a Dictionary<string, T> whereas I want a Dictionary<Role,App>.

Roles = Return.As<Dictionary<Role,App>>("COLLECT([role, app])") // doesn't work

I also considered creating the following class to use, but I can't find a way for it to work.

public class RoleWithApp
{
    public Role Role { get; set; }
    public App App { get; set; }
}

Roles = Return.As<List<RoleWithApp>>("COLLECT([role, app])") // doesn't work

I would be very grateful for some help with this, or a suggestion of a better way to do it.

Many thanks :)


回答1:


The problem lies with the way Neo4j returns your query results, if you execute your query in Neo4j and download the json for it, you end up with something like:

"[[{\"RoleName\":\"R1\"},{\"AppName\":\"A1\"}]]"

JSON.Net has no way to know how to parse this, it would require something in the form:

[{"Role":{"RoleName":"Bar"},"App":{"AppName":"Foo"}}]

The important bit being the "Role:" and "App:" definitions which guide JSON.Net to the right place.

Unfortunately - there's not a lot you can do about that, even if you read the values directly as in @LameCoder's example - you'll have to do some hokey parsing relating to the order, or maybe the properties on the things you get back.

Of course, if in the future we can do something like: COLLECT([role as Role, app as App]) then we'll be in good times...




回答2:


Hopefully someone gives a proper answer for the specific driver the question is for, but since in the comments I was asked how to do it manually and there's not enough room to put this in a comment I've made it an answer.

This is very basic and should help you get started trying to do this manually.

var to = "http://localhost:7474/db/data/cypher";
var reqMsg = new HttpRequestMessage("POST", to);
var cypher = @" ... ";
var parameters = new Dictionary<string, object>();

var req = new {
    query = cypher,
    @params = parameters //Use @ to be able to use a keyword as an identifier
};

var body = JToken.FromObject(req);

//You don't have to use streams if you don't want to. I just like to avoid creating large strings
reqMsg.Content = new PushStreamContent((stream, content, context) =>
                    {
                        using (var sw = new StreamWriter(stream))
                        using (var jw = new JsonTextWriter(sw))
                        {
                            body.WriteTo(jw);
                        }
                    }, "application/json");

using (var client = new HttpClient())
{
    var response = await client.SendAsync(reqMsg, HttpCompletionOption.ResponseHeadersRead);
    if (!response.IsSuccessStatusCode)
    {
        var s = await response.Content.ReadAsStringAsync();
        throw new Exception("Got status code " + response.StatusCode + " with error: " + s);
    }

    using (var reader = new JsonTextReader(new StreamReader(await response.Content.ReadAsStreamAsync())))
    {
        var o = JObject.Load(reader);
        return o;
    }

}


来源:https://stackoverflow.com/questions/19903518/how-to-return-collectrole-app-using-neo4jclient

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!