Neo4j 写入TraversalDescription以排除具有某些属性的边

Neo4j 写入TraversalDescription以排除具有某些属性的边,neo4j,Neo4j,我想写一个描述,我可以用步行者。我的最终目标是将Walker传递给GraphvizWriter,以便以.dot格式获得遍历结果 在我的图中,我只有一种类型的节点和一种类型的关系。每个关系都有一个名为“inCommon”的属性,该属性具有数值。我只需要在节点之间的关系上具有inCommon>=15的节点 下面是我的traversalDescription的样子: traversalDescription = graphDb.traversalDescription(); traversalDesc

我想写一个描述,我可以用步行者。我的最终目标是将Walker传递给GraphvizWriter,以便以.dot格式获得遍历结果

在我的图中,我只有一种类型的节点和一种类型的关系。每个关系都有一个名为“inCommon”的属性,该属性具有数值。我只需要在节点之间的关系上具有inCommon>=15的节点

下面是我的traversalDescription的样子:

traversalDescription = graphDb.traversalDescription();
traversalDescription = traversalDescription.breadthFirst();
traversalDescription = traversalDescription.evaluator(pathEvaluator);
traversalDescription = traversalDescription.relationships(type, Direction.BOTH);
pathEvaluator是我编写的一个类的实例,它试图只返回我想要的边

public class ReferentEvaluator implements PathEvaluator {
    @Override 
    public Evaluation evaluate(final Path path) {
        if(path!=null){
            Iterator iter=path.relationships().iterator();
            while(iter.hasNext()){
                Relationship r=(Relationship)iter.next();
                if(r!=null){
                    Integer inCommon=(Integer)r.getProperty(r.getPropertyKeys().iterator().next());
                    if(inCommon.intValue() < 15){
                        return Evaluation.EXCLUDE_AND_CONTINUE;
                    }
                }
                else{
                    return Evaluation.EXCLUDE_AND_CONTINUE;
                }
            }
            return Evaluation.INCLUDE_AND_CONTINUE;
        }
    return Evaluation.EXCLUDE_AND_CONTINUE;
    }
}
公共类引用评估器实现路径评估器{
@凌驾
公共评估(最终路径){
if(路径!=null){
迭代器iter=path.relationships().Iterator();
while(iter.hasNext()){
关系r=(关系)iter.next();
如果(r!=null){
整数inCommon=(整数)r.getProperty(r.getPropertyKeys().iterator().next());
if(inCommon.intValue()<15){
返回Evaluation.EXCLUDE_并_CONTINUE;
}
}
否则{
返回Evaluation.EXCLUDE_并_CONTINUE;
}
}
返回评估。包括_和_CONTINUE;
}
返回Evaluation.EXCLUDE_并_CONTINUE;
}
}

我看到的是,这不起作用。不常见<15的关系也包括在内。实际上,这种方法似乎根本不起作用。我是不是走错了路?或者我在这里做的事情越来越近了?

我认为在
路径扩展程序中实现关系过滤器比在
计算器中实现关系过滤器更好。这样做的原因是,您可以提前决定跳过哪些路径,而不需要加载节点并在以后过滤掉

您提供的不是
relationships()
而是一个自定义
PathExpander
PathExpander
使用谓词过滤给定类型的所有关系。谓词检查
inCommon
是否<15

由于我们在扩展器中完成了所有的脏活,因此我们可以节省使用一个计算器,该计算器使用
INCLUDE\u和\u CONTINUE
-
计算器进行回复。all()
可以完成这一操作

以下是我未经测试的代码片段:

import org.neo4j.helpers.Predicate;
import org.neo4j.helpers.collection.Iterables;
import ...

public void traversalSample() {

    TraversalDescription td = graphDatabaseService
            .traversalDescription()
            .expand(new RelationshipPropertyFilterExpander(
                    DynamicRelationshipType.withName("KNOWS"), Direction.BOTH, 
                    "inCommon", 15)
            )
            .evaluator(Evaluators.all());
    td.traverse(.....);
}

class RelationshipPropertyFilterExpander implements PathExpander<Object> {
    public RelationshipType type;
    public Direction direction;
    public String propName;
    int threshold;

    public RelationshipPropertyFilterExpander(RelationshipType type, Direction direction, 
                                              String propName, int threshold) {
        this.type = type;
        this.direction = direction;
        this.propName = propName;
        this.threshold = threshold;
    }

    @Override
    public Iterable<Relationship> expand(Path path, BranchState<Object> state) {
        Node endNode = path.endNode();
        Predicate<? super Relationship> predicate = new Predicate<Relationship>() {
            @Override
            public boolean accept(Relationship relationship) {
                // if relationship property is not set, we assume 0
                return Integer.parseInt(relationship.getProperty(propName, "0").toString()) < threshold;
            }
        };
        return Iterables.filter(predicate, endNode.getRelationships(type, direction));
    }

    @Override
    public PathExpander<Object> reverse() {
        // gets never called in a unidirectional traversal
        throw new UnsupportedOperationException();
    }
}
import org.neo4j.helpers.Predicate;
导入org.neo4j.helpers.collection.Iterables;
导入。。。
public void transversalsample(){
TraversalDescription td=graphDatabaseService
.traversalDescription()
.expand(新关系属性过滤Expander)(
DynamicRelationshipType.withName(“知道”),Direction.BOTH,
“不常见”,15)
)
.evaluator(Evaluators.all());
td.导线测量(…);
}
类RelationshipPropertyFilterExpander实现PathExpander{
公共关系类型;
公共方向;
公共字符串名称;
int阈值;
public RelationshipPropertyFilterExpander(RelationshipType类型、方向、,
字符串名称(整数阈值){
this.type=type;
这个方向=方向;
this.propName=propName;
这个阈值=阈值;
}
@凌驾
公共Iterable扩展(路径、分支状态){
Node endNode=path.endNode();

Predicate我认为在
PathExpander
中实现关系过滤器比在
Evaluator
中实现关系过滤器更好。原因是您可以提前决定跳过哪些路径,而不需要加载节点并在以后过滤掉

您提供的不是
relationships()
而是一个自定义
PathExpander
PathExpander
使用谓词过滤给定类型的所有关系。谓词检查
inCommon
是否<15

由于我们在扩展器中完成了所有的脏活,因此我们可以节省使用一个计算器,该计算器使用
INCLUDE\u和\u CONTINUE
-
计算器进行回复。all()
可以完成这一操作

以下是我未经测试的代码片段:

import org.neo4j.helpers.Predicate;
import org.neo4j.helpers.collection.Iterables;
import ...

public void traversalSample() {

    TraversalDescription td = graphDatabaseService
            .traversalDescription()
            .expand(new RelationshipPropertyFilterExpander(
                    DynamicRelationshipType.withName("KNOWS"), Direction.BOTH, 
                    "inCommon", 15)
            )
            .evaluator(Evaluators.all());
    td.traverse(.....);
}

class RelationshipPropertyFilterExpander implements PathExpander<Object> {
    public RelationshipType type;
    public Direction direction;
    public String propName;
    int threshold;

    public RelationshipPropertyFilterExpander(RelationshipType type, Direction direction, 
                                              String propName, int threshold) {
        this.type = type;
        this.direction = direction;
        this.propName = propName;
        this.threshold = threshold;
    }

    @Override
    public Iterable<Relationship> expand(Path path, BranchState<Object> state) {
        Node endNode = path.endNode();
        Predicate<? super Relationship> predicate = new Predicate<Relationship>() {
            @Override
            public boolean accept(Relationship relationship) {
                // if relationship property is not set, we assume 0
                return Integer.parseInt(relationship.getProperty(propName, "0").toString()) < threshold;
            }
        };
        return Iterables.filter(predicate, endNode.getRelationships(type, direction));
    }

    @Override
    public PathExpander<Object> reverse() {
        // gets never called in a unidirectional traversal
        throw new UnsupportedOperationException();
    }
}
import org.neo4j.helpers.Predicate;
导入org.neo4j.helpers.collection.Iterables;
导入。。。
public void transversalsample(){
TraversalDescription td=graphDatabaseService
.traversalDescription()
.expand(新关系属性过滤Expander)(
DynamicRelationshipType.withName(“知道”),Direction.BOTH,
“不常见”,15)
)
.evaluator(Evaluators.all());
td.导线测量(…);
}
类RelationshipPropertyFilterExpander实现PathExpander{
公共关系类型;
公共方向;
公共字符串名称;
int阈值;
public RelationshipPropertyFilterExpander(RelationshipType类型、方向、,
字符串名称(整数阈值){
this.type=type;
这个方向=方向;
this.propName=propName;
这个阈值=阈值;
}
@凌驾
公共Iterable扩展(路径、分支状态){
Node endNode=path.endNode();

谓词关于遍历框架,需要了解的重要一点是它在路径上运行。求值器总是获取从起始节点到图中当前位置的整个路径。因此,需要了解的第二个重要事项是,路径之间的区别状态更改是它们的结束节点。求值器将l每次调用
evaluate()
都会得到一个以新节点结尾的路径(有时取决于遍历的其他限制,请参见唯一性等)

这里重要的是,您的求值器总是遍历当前路径的所有边,并且在发现一条具有以下特性的边时立即进行迭代
    Evaluator traversal:
(6)
(6)--[KNOWS,0]-->(1)
(6)--[KNOWS,0]-->(1)<--[KNOWS,2]--(4)
(6)<--[KNOWS,1]--(3)--[KNOWS,6]-->(0)
(6)--[KNOWS,0]-->(1)<--[KNOWS,2]--(4)<--[KNOWS,3]--(5)
(6)<--[KNOWS,1]--(3)--[KNOWS,6]-->(0)<--[KNOWS,7]--(7)

Nodes with 'inCommon' edges >= 15:
Joe
Sara
Peter
Lars
Dirk
Nici