如何在具有多个标签的嵌入式Neo4j中获取节点?

时间:2015-09-01 18:16:05

标签: java neo4j

我有一个neo4j数据库,我使用嵌入式模式。每个节点有数百万个节点,其中有多个标签。我可以使用单个标签获取所有节点,如


    GlobalGraphOperations gb = GlobalGraphOperations.at(graphDb);
    ResourceIterable iterable = gb.getAllNodesWithLabel(DynamicLabel.label("LABEL1"));

这很好。现在我想做同样的事情,但有多个标签。我想要所有节点都有“LABEL1”和“LABEL2”和“LABEL3”等等。

2 个答案:

答案 0 :(得分:2)

内部Neo4j维护着一个labelscanstore,它为您提供了具有给定标签的所有节点的快速迭代器 - 但是对于标签组合没有这样的扫描存储。

如果要查找共享多个标签的所有节点,策略是迭代所有节点以获取“最便宜”的标签 - 也就是具有最少节点数的标签 - 并过滤其他标签。

下面的代码片段使用try-with-resources和JDK 8 lambda(n< JDK8的情况下只创建一个实现Predicate的类。我假设LABEL1是标签节点最少:

import org.neo4j.graphdb.*;
import org.neo4j.helpers.Predicate;
import org.neo4j.helpers.collection.FilteringIterator;

...

try (ResourceIterator<Node> nodes = 
    graphDatabaseService.findNodes(DynamicLabel.label("LABEL1"))) {

    Iterator<Node> nodeWithAllLabels = new FilteringIterator<>(nodes,
            node -> node.hasLabel(DynamicLabel.label("LABEL2")) && 
                    node.hasLabel(DynamicLabel.label("LABEL3"))
    );

    // do stuff with nodeWithAllLabels
}

答案 1 :(得分:2)

你可以execute a Cypher query。这是一段代码:

Map<String, Object> params = new HashMap<String, Object>();
params.put( "required", Arrays.asList( "LABEL1", "LABEL2", "LABEL3" ) );
String query = "MATCH (n) WHERE ALL(x IN {required} WHERE x IN LABELS(n)) RETURN n";
Result result = db.execute( query, params );

[UPDATE]

但是,上述查询将遍历所有节点,这些节点不具备性能。

感谢@ StefanArmbruster的建议,我们可以通过在MATCH子句中指定最不可能的标签(以利用内部生成的节点标签索引)来提高上述查询的效率:

Map<String, Object> params = new HashMap<String, Object>();
params.put( "otherLabels", Arrays.asList( "LABEL2", "LABEL3" ) );
String query = "MATCH (n:LABEL1) WHERE ALL(x IN {otherLabels} WHERE x IN LABELS(n)) RETURN n";
Result result = db.execute( query, params );