如何return多个节点使用最短路径?
How to return multiple nodes using shortest path?
我正在尝试用 C# 重新创建它:
MATCH p=shortestPath((bacon:Person {name:"Kevin Bacon"})-[*]-(meg:Person {name:"Meg Ryan"}))
RETURN p
但我发现所有示例仅使用最短路径 returns 是相同类型节点的列表。在这个例子中,我需要 return People 和 Movies 节点。
所以它开始是这样的:
var shortestPath = graphClient.Cypher
.OptionalMatch("p = shortestPath((bacon: Person )-[*] - (meg: Person ) )")
.Where((Person bacon) => bacon.name == "Kevin Bacon ")
.AndWhere((Person meg) => meg.name == "Meg Ryan")
.Return(?)
.Results;
我应该写什么而不是问号?
图表如下所示:
更新:
我在 neo4j 客户端的最短路径上找到的唯一信息是 Return All Nodes in Shortest Path as Object List 但我无法弄清楚。
好问题 - 很难解决,我想我已经做到了 - 虽然 - 它可能不是最高效的。
正如您所说 - 问题是多种类型 - 所以让我们开始设置,我正在使用扩展方法来使代码看起来更好一些:
public static class Extensions
{
public static T ToObject<T>(this string value)
{
//deserialize into a 'Node' first
var node = JsonConvert.DeserializeObject<Node>(value);
//then take the 'data' from that and 'ToObject' to the correct thing.
return ((JObject) node.data).ToObject<T>();
}
private class Node{
public object data {get;set;}
}
}
ToObject<T>
方法是我们用来将输出转换为对象的方法。
我有一套标准的 POCO 来表示数据(尽管属性的命名约定很糟糕):
public class Movie {
public string title {get;set;}
public string tagline {get;set;}
}
public class Person {
public string name {get;set;}
public int born {get;set;}
}
public class RolesRel {
public IEnumerable<string> roles {get;set;}
}
好的 - 现在我们准备好了。我已将 Return
更改为如下所示:
var shortestPath = graphClient.Cypher
.OptionalMatch("p = shortestPath((bacon: Person)-[*]-(meg: Person ) )")
.Where((Person bacon) => bacon.name == "Kevin Bacon")
.AndWhere((Person meg) => meg.name == "Meg Ryan")
.Return(p => new {
Nodes = Return.As<IEnumerable<string>>("nodes(p)"),
Relationships = Return.As<IEnumerable<RolesRel>>("rels(p)")
});
string
是我们用于反序列化多个节点类型的唯一通用选项。在这种情况下,由于关系都是相同的,我们在这方面都很好,只使用 POCO - 但如果不是这样,你最终也会为他们做我们为节点所做的事情。
接下来,我运行通过结果:
foreach (var result in shortestPath.Results)
{
foreach (var node in result.Nodes)
{
if(node.Contains("name"))
Console.WriteLine(node.ToObject<Person>().name);
else if(node.Contains("title"))
Console.WriteLine(node.ToObject<Movie>().title);
else {
Console.WriteLine("Unknown Node Type: " + node);
}
}
}
我在这里对 属性 名称进行天真的检查,我知道它属于一种节点类型,但不属于另一种节点类型 - 您可能想以另一种方式进行 - 但这是可行的。
显然 - 我只是输出到屏幕 - 但你可以访问对象本身。
我正在尝试用 C# 重新创建它:
MATCH p=shortestPath((bacon:Person {name:"Kevin Bacon"})-[*]-(meg:Person {name:"Meg Ryan"}))
RETURN p
但我发现所有示例仅使用最短路径 returns 是相同类型节点的列表。在这个例子中,我需要 return People 和 Movies 节点。 所以它开始是这样的:
var shortestPath = graphClient.Cypher
.OptionalMatch("p = shortestPath((bacon: Person )-[*] - (meg: Person ) )")
.Where((Person bacon) => bacon.name == "Kevin Bacon ")
.AndWhere((Person meg) => meg.name == "Meg Ryan")
.Return(?)
.Results;
我应该写什么而不是问号?
图表如下所示:
更新: 我在 neo4j 客户端的最短路径上找到的唯一信息是 Return All Nodes in Shortest Path as Object List 但我无法弄清楚。
好问题 - 很难解决,我想我已经做到了 - 虽然 - 它可能不是最高效的。
正如您所说 - 问题是多种类型 - 所以让我们开始设置,我正在使用扩展方法来使代码看起来更好一些:
public static class Extensions
{
public static T ToObject<T>(this string value)
{
//deserialize into a 'Node' first
var node = JsonConvert.DeserializeObject<Node>(value);
//then take the 'data' from that and 'ToObject' to the correct thing.
return ((JObject) node.data).ToObject<T>();
}
private class Node{
public object data {get;set;}
}
}
ToObject<T>
方法是我们用来将输出转换为对象的方法。
我有一套标准的 POCO 来表示数据(尽管属性的命名约定很糟糕):
public class Movie {
public string title {get;set;}
public string tagline {get;set;}
}
public class Person {
public string name {get;set;}
public int born {get;set;}
}
public class RolesRel {
public IEnumerable<string> roles {get;set;}
}
好的 - 现在我们准备好了。我已将 Return
更改为如下所示:
var shortestPath = graphClient.Cypher
.OptionalMatch("p = shortestPath((bacon: Person)-[*]-(meg: Person ) )")
.Where((Person bacon) => bacon.name == "Kevin Bacon")
.AndWhere((Person meg) => meg.name == "Meg Ryan")
.Return(p => new {
Nodes = Return.As<IEnumerable<string>>("nodes(p)"),
Relationships = Return.As<IEnumerable<RolesRel>>("rels(p)")
});
string
是我们用于反序列化多个节点类型的唯一通用选项。在这种情况下,由于关系都是相同的,我们在这方面都很好,只使用 POCO - 但如果不是这样,你最终也会为他们做我们为节点所做的事情。
接下来,我运行通过结果:
foreach (var result in shortestPath.Results)
{
foreach (var node in result.Nodes)
{
if(node.Contains("name"))
Console.WriteLine(node.ToObject<Person>().name);
else if(node.Contains("title"))
Console.WriteLine(node.ToObject<Movie>().title);
else {
Console.WriteLine("Unknown Node Type: " + node);
}
}
}
我在这里对 属性 名称进行天真的检查,我知道它属于一种节点类型,但不属于另一种节点类型 - 您可能想以另一种方式进行 - 但这是可行的。
显然 - 我只是输出到屏幕 - 但你可以访问对象本身。