Neo4J以正确的顺序遍历两种不同的关系?

时间:2014-12-31 11:28:23

标签: neo4j

我正在使用Neo4J Traversal API并试图从“1”遍历以找到符合下面模式的节点“2”和“3”:

1-[:A]-2-[:B]-3

然而,在我的遍历中,我被抓住了,因为还存在以下关系:

1-[:B]-3

据我了解,我的TraversalDescription需要指定两种关系类型,但我不确定最优雅的方式来遍历:首先是关系,然后分支到:B关系。不幸的是,Direction关系不能用来区分我的情况。

我的Scala代码是:

db.traversalDescription()
    .evaluator(isAThenBRelationship)
    .breadthFirst()
    .relationships(A)
    .relationships(B)

private val isAThenBRelationship = new PathEvaluator.Adapter() {
override def evaluate(path: Path, state: BranchState[Nothing]): Evaluation = {
  if (path.length == 0) {
    EXCLUDE_AND_CONTINUE
  } else if (path.length == 1) {
    Evaluation.of(false, path.relationships().iterator().next().getType.name() == A.toString)
  } else {
    Evaluation.of(path.relationships().iterator().next().getType.name() == B.toString, false)
  }
}

}

顺便说一下,比较关系比这更好的方法是什么?

path.relationships().iterator().next().getType.name() == MyRelationship.toString

2 个答案:

答案 0 :(得分:2)

多次使用relationships()并不意味着订单。相反,有一个内部列表,relationships()添加了一些内容。

要将特定关系类型限制为特定深度,您需要实现并使用自己的PathExpander。下面的示例使用Java并使用匿名内部类实现PathExpander

traversalDescription.expand(new PathExpander<Object>() {
    @Override
    public Iterable<Relationship> expand(Path path, BranchState<Object> state) {
        switch (path.length()) {
            case 0:
                return path.endNode().getRelationships(
                    DynamicRelationshipType.withName("A") );
            case 1:
                return path.endNode().getRelationships(
                    DynamicRelationshipType.withName("B") );
            default:
                return Iterables.empty();
        }
    }

    @Override
    public PathExpander<Object> reverse() {
        // not used for unidirectional traversals
        throw new UnsupportedOperationException();
    }
});

关于你的第二个问题:

Neo4j包含一个非常方便的类IteratorUtils。因此,您的代码段可以写为(假设MyRelationship是RelationshipType的实例:

 IteratorUtil.first(path.relationships()).getType().equals(MyRelationship)

答案 1 :(得分:1)

除了@ StefanArmbruster的回答,这里是等效的Scala代码:

db.traversalDescription()
  .breadthFirst()
  .expand(isAThenBRelationship)

private val isAThenBRelationship = 
   new PathExpander[Object]() {
     override def expand(path: Path, state: BranchState[Object]) =
       path.length() match {
         case 0 => path.endNode().getRelationships(DynamicRelationshipType.withName("A"))
         case 1 => path.endNode().getRelationships(DynamicRelationshipType.withName("B"))
         case _ => Iterables.empty()
       }

     override def reverse(): PathExpander[Object] = ???
   }

请注意,扩展器必须在关系之后。