Neo4j - 遍历以找到特定的连接组件
Posted
技术标签:
【中文标题】Neo4j - 遍历以找到特定的连接组件【英文标题】:Neo4j - traversal to find specific connected component 【发布时间】:2013-11-07 17:48:39 【问题描述】:使用neo4j 1.9.4,我试图从关系具有特定属性('since')的起始节点找到连接的组件(所有可达节点),并且该属性具有定义的整数值,例如20130101.
我最初的方法是使用密码查询,但我觉得如果图表中有循环,这个查询会循环到无穷大?至少如果我不限制路径长度并且限制长度不是我想要做的。
所以同时我开始使用遍历。使用 neo4jphp 遍历看起来像这样:
$traversal->setOrder(Everyman\Neo4j\Traversal::OrderBreadthFirst)
->setPruneEvaluator(Everyman\Neo4j\Traversal::PruneNone)
->setReturnFilter(Everyman\Neo4j\Traversal::ReturnAll)
->setUniqueness(Everyman\Neo4j\Traversal::UniquenessNodeGlobal);
我认为我需要的是这样的:
->setPruneEvaluator('javascript', "position.RELATIONSHIP().getProperty('since').EQUALS(20130101)")
显然,RELATIONSHIP 和 EQUALS 似乎是错误的。 我从示例 https://github.com/jadell/neo4jphp/wiki/Traversals 中采用了这一点,其中设置了以下有效且有效的 pruneElevater:
->setPruneEvaluator('javascript', "position.endNode().getProperty('name').toLowerCase().contains('t')")
我完全不熟悉 JavaScript,所以我不知道该怎么做。此外,如果存在不具有属性“since”的关系,我如何确保遍历不会导致错误? 如果我可以使用密码查询来达到同样的效果,我也会接受。
编辑:顺便说一下,我使用密码的方法是这样的:
START n=node(start_node) MATCH p = n-[*]-m WHERE ALL(x IN RELATIONSHIPS(p) WHERE HAS(x.since) AND x.since = 20130101) RETURN DISTINCT m
EDIT2:尝试来自 ulkas 的建议密码查询给我以下错误:
Invalid query
string matching regex ``(``|[^`])*`' expected but `*' found
Think we should have better error message here? Help us by sending this query to cypher@neo4j.org.
Thank you, the Neo4j Team.
"START n=node(40317) MATCH p = n-[r:*..]-m WHERE has(r.since) AND r.since = 20130101 RETURN DISTINCT m"
^
EDIT3:LameCode 的建议看起来很有希望,但仍然返回错误:
Fatal error: Uncaught exception 'Everyman\Neo4j\Exception' with message 'Unable to execute traversal [400]: Headers: Array ( [Content-Length] => 5183 [Content-Type] => application/json; charset=UTF-8 [Access-Control-Allow-Origin] => * [Server] => Jetty(6.1.25) ) Body: Array ( [message] => Failed to execute script, see nested exception. [exception] => EvaluationException [fullname] => org.neo4j.server.rest.domain.EvaluationException [stacktrace] => Array ( [0] => org.neo4j.server.scripting.javascript.JavascriptExecutor.execute(JavascriptExecutor.java:118) [1] => org.neo4j.server.rest.domain.EvaluatorFactory$ScriptedEvaluator.evalPosition(EvaluatorFactory.java:140) [2] => org.neo4j.server.rest.domain.EvaluatorFactory$ScriptedPruneEvaluator.evaluate(EvaluatorFactory.java:161) [3] => org.neo4j.graphdb.traversal.Evaluator$AsPathEvaluator.evaluate(Evaluator.java:69) [4] => org.neo4j.kernel.impl.traversal.TraverserIterator.eva in /var/www/vendor/everyman/neo4jphp/lib/Everyman/Neo4j/Command.php on line 116
我使用了以下 pruneEvaluator:
->setPruneEvaluator('javascript', "position.lastRelationship().hasProperty('since') && position.lastRelationship().getProperty('since') == 20130101")
当从 lastRelationship() 更改为 endNode() 时,它至少不会返回错误,尽管我想知道它返回的许多结果,如没有一个节点具有这个自属性?!因此,即使在那时,修剪评估器似乎也没有开始工作。如果没有自属性或者它不等于给定日期,我希望它在每个 endNode 处停止?我做错了什么,有什么想法吗?
【问题讨论】:
带有密码的循环应该不是问题。也许修改它像START n=node(start_node) MATCH p = n-[r:*..]-m WHERE has(r.since) AND r.since = 20130101 RETURN DISTINCT m
尝试这个查询会给我以下错误:无效的查询字符串匹配正则表达式 (
|[^])*
' 预期但 `*' 认为我们应该在这里有更好的错误消息?通过将此查询发送到 cypher@neo4j.org 来帮助我们。谢谢 Neo4j 团队。 "START n=node(40317) MATCH p = n-[r:*..]-m WHERE has(r.since) AND r.since = 20130101 RETURN DISTINCT m" ^
你是对的,*..
语法只能用于特定的关系类型,无论出于何种原因。现在我找不到比你用where all
更好的密码语句了。也许重新设计图表并使每个日期像20130101
一个节点而不是rel?
【参考方案1】:
关于您正在使用的 Traverser。 javascript prune evaluator 'position' 变量是一个 Path 对象。见:http://components.neo4j.org/neo4j/1.9.4/apidocs/org/neo4j/graphdb/Path.html
你应该可以使用这些方法。
使用lastRelationship()
(因为之前的所有关系都已经通过修剪评估器)。
Relationship 对象继承自 Property Container 并具有 hasProperty()
方法。
setPruneEvaluator('javascript', "position.lastRelationship().hasProperty('since') && position.lastRelationship().getProperty('since') == 20130101")
我不确定你是否需要使用 Equals 方法,因为它是 javascript。
【讨论】:
我尝试了你的建议,看起来确实是我想要的,但它仍然返回错误,请参阅上面的编辑 看来,根据文档 lastRelationship() 可以返回 null。它可能适用于第一条路径(我想它本身就是节点)。所以尝试在开头添加 position.lastRelationship() != null &&。 就是这样!没有错误了。不过,我不太确定 prune evaluator 是否真的按照我想要的方式部署。即使关系具有不同的“自”属性,似乎遍历仍在继续。但无论如何,谢谢你的帮助以上是关于Neo4j - 遍历以找到特定的连接组件的主要内容,如果未能解决你的问题,请参考以下文章