我试图通过Maven Java Application在Neo4j中创建一些节点,并在这些节点之间创建关系。我想要创建16807个节点和17210368关系。我读取了一个文件并获取了row
变量,该变量具有我必须创建的节点数,并且我还有一个list
,其中有34420736个元素(= 17210368 * 2)。我想创建一个从节点[列表的元素0]到节点[列表中的元素1],从节点[列表的元素2]到节点[列表中的元素3]等的关系。此外,列表的最大元素是16807。我创建ArrayList<Node>
以动态创建节点,因为我希望程序使用不同的文件(以及不同的行值)运行。
这是我的代码:
GraphDatabaseFactory dbFactory = new GraphDatabaseFactory();
GraphDatabaseService graphDb = dbFactory.newEmbeddedDatabase("C:\Users\....\default.graphdb");
Transaction tx = graphDb.beginTx();
try {
final RelationshipType type2 = DynamicRelationshipType.withName("KNOW");
ArrayList<Node> nodelist = new ArrayList<Node>();
for (int k = 0; k < row; k++) { //row=16807
nodelist.add(graphDb.createNode());
nodelist.get(k).setProperty("Name", "ListNode " + k);
}
int count=0;
for (int j = 0; j < list.size() ; j++) { //list.size()=34420736
nodelist.get(list.get(count)).createRelationshipTo(nodelist.get(list.get(count+1)), type2);
count=count+2;
}
tx.success();
}
finally {
tx.close();
}
graphDb.shutdown();
如果我在不尝试创建关系的情况下运行代码,则会创建节点并正确运行。当我添加创建真实关系的for循环时,它会抛出以下错误:
Exception in thread "main" org.neo4j.graphdb.TransactionFailureException: Unable to rollback transaction
at org.neo4j.kernel.TopLevelTransaction.close(TopLevelTransaction.java:131)
at com.mycompany.traverse_test.traverse_main.main(traverse_main.java:138)
Caused by: java.lang.IllegalStateException: No RelationshipState for added relationship!
at org.neo4j.kernel.api.txstate.RelationshipChangeVisitorAdapter$1.visit(RelationshipChangeVisitorAdapter.java:132)
at org.neo4j.kernel.api.txstate.RelationshipChangeVisitorAdapter.visitAddedRelationship(RelationshipChangeVisitorAdapter.java:83)
at org.neo4j.kernel.api.txstate.RelationshipChangeVisitorAdapter.visitAdded(RelationshipChangeVisitorAdapter.java:106)
at org.neo4j.kernel.api.txstate.RelationshipChangeVisitorAdapter.visitAdded(RelationshipChangeVisitorAdapter.java:47)
at org.neo4j.kernel.impl.util.diffsets.DiffSets.accept(DiffSets.java:76)
at org.neo4j.kernel.impl.api.state.TxState.accept(TxState.java:156)
at org.neo4j.kernel.impl.api.KernelTransactionImplementation.rollback(KernelTransactionImplementation.java:542)
at org.neo4j.kernel.impl.api.KernelTransactionImplementation.close(KernelTransactionImplementation.java:404)
at org.neo4j.kernel.TopLevelTransaction.close(TopLevelTransaction.java:112)
... 1 more
任何想法??
答案 0 :(得分:1)
由于您的代码中存在错误,Neo4j正在尝试回滚您的交易。它无法回滚的事实可能是neo4j中的一个错误,但这确实不是你的主要问题。
查看您的代码,看起来您正在迭代list
太多次。也就是说,list
循环中的代码一次使用了2个列表元素,因此您应该只循环list.size()/2
次。
以下是应该修复该错误的代码,并且还进行了一些其他改进。
GraphDatabaseFactory dbFactory = new GraphDatabaseFactory();
GraphDatabaseService graphDb = dbFactory.newEmbeddedDatabase("C:\Users\....\default.graphdb");
Transaction tx = graphDb.beginTx();
try {
final RelationshipType type2 = DynamicRelationshipType.withName("KNOW");
ArrayList<Node> nodelist = new ArrayList<Node>();
for (int k = 0; k < row; k++) { //row=16807
Node node = graphDb.createNode();
node.setProperty("Name", "ListNode " + k);
nodelist.add(node);
}
for (int j = 0; j < list.size() ; j += 2) { //list.size()=34420736
nodelist.get(list.get(j)).createRelationshipTo(
nodelist.get(list.get(j+1)), type2);
}
tx.success();
} catch(Throwable e) {
e.printStackTrace();
// You may want to re-throw the exception, rather than just eating it here...
} finally {
tx.close();
}
graphDb.shutdown();
[EDITED]
但是,上述代码仍然可能内存不足,因为它试图在单个事务中创建这么多资源(16K节点和17M关系)。
以下示例代码在多个事务中执行(一个用于创建节点和节点列表,多个事务用于关系)。
NUM_RELS_PER_CHUNK
指定每个事务中要创建的最大关系数。必须修改createRelEndpointList()
方法以填写关系端点(节点)索引列表(每个索引是nodeList
中节点的0原点位置。)
public class MyCode {
private static final int NODE_COUNT = 16807;
private static final int NUM_RELS_PER_CHUNK = 1000000;
public static void main(String[] args) {
doIt();
}
private static void doIt() {
GraphDatabaseFactory dbFactory = new GraphDatabaseFactory();
GraphDatabaseService graphDb = dbFactory.newEmbeddedDatabase(new File("C:\\Users\\....\\default.graphdb"));
try {
RelationshipType type = DynamicRelationshipType.withName("KNOW");
List<Node> nodeList = createNodes(graphDb, NODE_COUNT);
List<Integer> list = createRelEndpointList();
final int numRels = list.size() / 2;
final int numChunks = (numRels + NUM_RELS_PER_CHUNK - 1)/NUM_RELS_PER_CHUNK;
int startRelIndex = 0, endRelIndexPlus1;
for (int i = numChunks; --i >= 0 && startRelIndex < numRels; ) {
endRelIndexPlus1 = (i > 0) ? startRelIndex + NUM_RELS_PER_CHUNK : numRels;
createRelationships(graphDb, nodeList, list, startRelIndex, endRelIndexPlus1, type);
startRelIndex = endRelIndexPlus1;
}
} finally {
graphDb.shutdown();
}
}
private static List<Node> createNodes(GraphDatabaseService graphDb, int rowCount) {
ArrayList<Node> nodeList = new ArrayList<Node>(rowCount);
Transaction tx = graphDb.beginTx();
try {
final StringBuilder sb = new StringBuilder("ListNode ");
final int initLength = sb.length();
for (int k = 0; k < rowCount; k++) {
Node node = graphDb.createNode();
sb.setLength(initLength);
sb.append(k);
node.setProperty("Name", sb.toString());
nodeList.add(node);
}
tx.success();
System.out.println("Created nodes.");
} catch(Exception e) {
e.printStackTrace();
tx.failure();
return null;
} finally {
tx.close();
}
return nodeList;
}
private static List<Integer> createRelEndpointList() {
final List<Integer> list = new ArrayList<Integer>();
// Fill
// list
// ...
return list;
}
private static void createRelationships(GraphDatabaseService graphDb, List<Node> nodeList, List<Integer> list, int startRelIndex, int endRelIndexPlus1, RelationshipType type) {
Transaction tx = graphDb.beginTx();
try {
final int endPlus2 = endRelIndexPlus1 * 2;
for (int j = startRelIndex * 2; j < endPlus2; ) {
Node from = nodeList.get(list.get(j++));
Node to = nodeList.get(list.get(j++));
from.createRelationshipTo(to, type);
}
tx.success();
System.out.println("Created rels. Start: " + startRelIndex + ", count: " + (endRelIndexPlus1 - startRelIndex));
} catch(Exception e) {
e.printStackTrace();
tx.failure();
// You may want to re-throw the exception, rather than just eating it here...
} finally {
tx.close();
}
}
}