我有一个neo4j数据库,我使用嵌入式模式。每个节点有数百万个节点,其中有多个标签。我可以使用单个标签获取所有节点,如
GlobalGraphOperations gb = GlobalGraphOperations.at(graphDb);
ResourceIterable iterable = gb.getAllNodesWithLabel(DynamicLabel.label("LABEL1"));
这很好。现在我想做同样的事情,但有多个标签。我想要所有节点都有“LABEL1”和“LABEL2”和“LABEL3”等等。
答案 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 );