Neo4j .NET客户端 - 获取从节点到其根节点的路径

时间:2013-12-18 13:33:03

标签: .net neo4j graph-databases neo4jclient

我是第一次尝试使用Neo4j。 我在控制台(Cypher查询)上玩了一下,现在我尝试使用.NET客户端为.NET应用程序构建DAL。

目前,我的数据模型非常简单:

  • 我有带标签的节点"文件夹"。
  • 这些节点可能有一个" HAS_SUB_FOLDER"与其他文件夹节点的关系。

我已成功完成了一些查询,例如

MATCH (n:Folder) 
OPTIONAL MATCH n<-[r:HAS_SUB_FOLDER]-parent 
WITH n, count(parent) AS parents 
WHERE parents = 0 
RETURN n;

获取无父节点(即&#34;根目录中的文件夹&#34;),转换为:

var myQuery = client.Cypher.Match("(folder:Folder)")
            .OptionalMatch("folder<-[r:HAS_SUB_FOLDER]-parent")
            .With("folder, count(parent) AS parents")
            .Where("parents=0")
            .Return<Folder>("folder");
        var res = myQuery.Results.ToList();
// res is a List<Folder>, Folder is a Model in my MVC architecture containing attributes like an ID and a Name.

在.NET中。

现在,我正在尝试,对于给定的文件夹节点,找到其根目录的路径(以创建一些导航面包屑)。我为此写的查询是:

MATCH (current:Folder {id: "...THE_ID..."})
MATCH p = ((current)<-[:HAS_SUB_FOLDER*1..5000]-())
RETURN p;

似乎有用。

但是,我无法使用.NET客户端实现这一目标。我想获得一个包含给定节点的祖先文件夹的List。我试过了:

var getPathToRoot = client.Cypher.Match("(current:Folder)")
            .Where((Folder current) => current.ID == id)
            .Match("p = ((current) <- [:HAS_SUB_FOLDER*1.." + MAX_DEPTH + "]-())")
            .Return<Folder>("NODES(p)");
var result = myQuery.Results.ToList();

但我得到一个:Accessed JArray values with invalid key value: "self". Array position index expected.,其中包含以下原始JSON:

{
  "columns" : [ "NODES(p)" ],
  "data" : [ [ [ {
    "labels" : "http://localhost:7474/db/data/node/21721/labels",
    "outgoing_relationships" : "http://localhost:7474/db/data/node/21721/relationships/out",
    "data" : {
      "Name" : "YYYYYYYY",
      "ID" : "e5daef28-84c0-42a8-85bf-32516bfe47d0"
    },
    "traverse" : "http://localhost:7474/db/data/node/21721/traverse/{returnType}",
    "all_typed_relationships" : "http://localhost:7474/db/data/node/21721/relationships/all/{-list|&|types}",
    "property" : "http://localhost:7474/db/data/node/21721/properties/{key}",
    "self" : "http://localhost:7474/db/data/node/21721",
    "outgoing_typed_relationships" : "http://localhost:7474/db/data/node/21721/relationships/out/{-list|&|types}",
    "properties" : "http://localhost:7474/db/data/node/21721/properties",
    "incoming_relationships" : "http://localhost:7474/db/data/node/21721/relationships/in",
    "extensions" : {
    },
    "create_relationship" : "http://localhost:7474/db/data/node/21721/relationships",
    "paged_traverse" : "http://localhost:7474/db/data/node/21721/paged/traverse/{returnType}{?pageSize,leaseTime}",
    "all_relationships" : "http://localhost:7474/db/data/node/21721/relationships/all",
    "incoming_typed_relationships" : "http://localhost:7474/db/data/node/21721/relationships/in/{-list|&|types}"}, 
    {
    "labels" : "http://localhost:7474/db/data/node/21720/labels",
    "outgoing_relationships" : "http://localhost:7474/db/data/node/21720/relationships/out",
    "data" : {
       "Name" : "XXXXXXXX",
       "ID" : "31a4cde4-8584-418f-a122-a0f84bbfbf92"
    },
    "traverse" : "http://localhost:7474/db/data/node/21720/traverse/{returnType}",
    "all_typed_relationships" : "http://localhost:7474/db/data/node/21720/relationships/all/{-list|&|types}",
    "property" : "http://localhost:7474/db/data/node/21720/properties/{key}",
    "self" : "http://localhost:7474/db/data/node/21720",
    "outgoing_typed_relationships" : "http://localhost:7474/db/data/node/21720/relationships/out/{-list|&|types}",
    "properties" : "http://localhost:7474/db/data/node/21720/properties",
    "incoming_relationships" : "http://localhost:7474/db/data/node/21720/relationships/in",
    "extensions" : {
    },
    "create_relationship" : "http://localhost:7474/db/data/node/21720/relationships",
    "paged_traverse" : "http://localhost:7474/db/data/node/21720/paged/traverse/{returnType}{?pageSize,leaseTime}",
    "all_relationships" : "http://localhost:7474/db/data/node/21720/relationships/all",
    "incoming_typed_relationships" : "http://localhost:7474/db/data/node/21720/relationships/in/{-list|&|types}"
  } ] ] ]
}

我可以看到正在检索我想要的数据,但在反序列化时似乎存在问题。我在代码上尝试了一些变化,没有成功,我相信在尝试从检索到的路径中获取节点时,我在某个地方遇到了新手错误。

我很高兴有人可以帮助我,因为我刚刚开始使用Neo4j(而且我还是#34;硬连线&#34; 认为RDBMS ),文档(仍然)有点稀疏,我有调试问题(每当我试图从Neo4j客户端库中查看任何变量的值时,我得到一个&#34;函数评估因为先前的功能评估超时而被禁用。您必须继续执行以重新启用功能评估。&#34;)。

1 个答案:

答案 0 :(得分:3)

你很亲密。只需将路径中的节点返回为IEnumerable<Folder>

var getPathToRoot = client.Cypher.Match("(current:Folder)")
    .Where((Folder current) => current.ID == id)
    .Match("p = ((current) <- [:HAS_SUB_FOLDER*1.." + MAX_DEPTH + "]-())")
    .Return(() => Return.As<IEnumerable<Folder>>("nodes(p)"));

此可变长度匹配实际上将返回多个路径。如果您想要最长的路径,直到树的根,请按路径长度(降序)对结果进行排序,并将其限制为1.

你也可以省略可变长度路径的minHops和maxHops,因为它们默认为1和无穷大。你可以省略maxHops,因为它默认为无穷大但是我将minHops设置为0;否则你不能将此查询用于根节点本身。

这就是我写它的方式:

var pathToRoot = client.Cypher
    .Match("p = (current:Folder)<-[:HAS_SUB_FOLDER*0..]-()")
    .Where((Folder current) => current.ID == id)
    .Return(() => Return.As<IEnumerable<Folder>>("nodes(p)"))
    .OrderByDescending("length(p)")
    .Limit(1).Results.SingleOrDefault();