我遇到的问题是,在我将AutoIndex索引设为某个属性之后,我可以添加一个键/值对,并且索引不会显示它在那里。我对neo4j比较陌生,所以我对这个类应该做的概念可能是错误的。测试代码创建一个非永久性图形数据库,用它实例化我的数据服务类,然后创建一个用户。实例化数据服务类时,就是将属性添加到AutoIndex时。你可以在createUser()函数里面看到,我已经打印出我刚刚创建的用户并且应该在AutoIndex中,但是它打印为null。
这是我正在测试的代码:
@Before
public void setup() throws IOException {
graphDb = new ImpermanentGraphDatabase();
Transaction tx = graphDb.beginTx();
try {
nA = graphDb.createNode();
nB = graphDb.createNode();
packetA = graphDb.createNode();
packetB = graphDb.createNode();
dataService = new DataServiceImpl(graphDb);
tx.success();
}
finally
{
tx.finish();
}
}
/****************** Test User Creation Functionality *******************/
@Test
public void createUser() throws ExistsException {
Transaction tx = graphDb.beginTx();
try {
UserWrapper user = (UserWrapper) dataService.createUser(BigInteger.valueOf(1));
tx.success();
}
finally {
tx.finish();
}
}
以下是DataServiceImpl中的代码:
/**
* Node property keys that should be auto-indexed.
*/
private static final Set<String> NODE_KEYS_INDEXABLE = new HashSet<String>(
Arrays.asList(new String[] { UserWrapper.KEY_IDENTIFIER }));
/**
* Relationship property keys that should be auto-index.
*/
private static final Set<String> REL_KEYS_INDEXABLE = new HashSet<String>(
Arrays.asList(new String[] { SentWrapper.TIME_PROP }));
private void initIndices() {
/* Get the auto-indexers */
AutoIndexer<Node> nodeAutoIndexer = this.graphDb.index()
.getNodeAutoIndexer();
RelationshipAutoIndexer relAutoIndexer = this.graphDb.index()
.getRelationshipAutoIndexer();
this.updateIndexProperties(nodeAutoIndexer,
DataServiceImpl.NODE_KEYS_INDEXABLE);
this.nodeIndex = nodeAutoIndexer.getAutoIndex();
this.updateIndexProperties(relAutoIndexer,
DataServiceImpl.REL_KEYS_INDEXABLE);
this.relIndex = relAutoIndexer.getAutoIndex();
}
/**
* Sets the indexed properties of an {@link AutoIndexer} to the specified
* set, removing old properties and adding new ones.
*
* @param autoIndexer
* the AutoIndexer to update.
* @param properties
* the properties to be indexed.
* @return autoIndexer, this given AutoIndexer (useful for chaining calls.)
*/
private <T extends PropertyContainer> AutoIndexer<T> updateIndexProperties(
AutoIndexer<T> autoIndexer, Set<String> properties) {
Set<String> indexedProps = autoIndexer.getAutoIndexedProperties();
// Remove unneeded properties.
for (String prop : difference(indexedProps, properties)) {
autoIndexer.stopAutoIndexingProperty(prop);
}
// Add new properties.
for (String prop : difference(properties, indexedProps)) {
autoIndexer.startAutoIndexingProperty(prop);
}
// Enable the index, if needed.
if (!autoIndexer.isEnabled()) {
autoIndexer.setEnabled(true);
}
return autoIndexer;
}
public User createUser(BigInteger identifier) throws ExistsException {
// Verify that user doesn't already exist.
if (this.nodeIndex.get(UserWrapper.KEY_IDENTIFIER, identifier).getSingle() != null) {
throw new ExistsException("User with identifier '" + identifier.toString() + "' already exists.");
}
// Create new user.
final Node userNode = graphDb.createNode();
final User user = new UserWrapper(userNode);
user.setIdentifier(identifier);
Node userNode2 = this.nodeIndex.get(UserWrapper.KEY_IDENTIFIER, identifier).getSingle();
System.out.println(userNode2);
userParent.getNode().createRelationshipTo(userNode, NodeRelationships.PARENT);
return user;
}
以下是UserWrapper中的代码:
/**
* Mapping to neo4j key for the identifier property.
*/
//Changed to public in order to test in Test class
static final String KEY_IDENTIFIER = "identifier";
@Override
public void setIdentifier(BigInteger newIdentity) {
neo4jNode.setProperty(KEY_IDENTIFIER, newIdentity.toByteArray());
}
答案 0 :(得分:2)
你在哪里添加第二个用户?通过运行测试两次?然后ImpermanentGraphDatabase
将在第二次运行之前删除所有数据(因为它用于测试)。索引在提交时发生,并在事务期间聚合所有更改,这就是您在tx(userNode2)中看不到它的原因。如果您愿意,可以将此检查添加到测试中(见下文)。
从你的代码中,在你拨打initIndices
的地方也看不到它,你能指出一下这个地方吗?还请验证自动索引器是否正确索引正确的属性。
尝试将测试更改为,然后第二次调用应抛出异常:
@Test(expected = ExistsException.class)
public void createUser() throws ExistsException {
Transaction tx = graphDb.beginTx();
try {
UserWrapper user = (UserWrapper) dataService.createUser(BigInteger.valueOf(1));
tx.success();
}
finally {
tx.finish();
}
Node userNode2 = this.graphDb.index().getNodeAutoIndexer().getAutoIndex().get(UserWrapper.KEY_IDENTIFIER, identifier).getSingle();
assertNotNull(userNode2);
Transaction tx = graphDb.beginTx();
try {
UserWrapper user = (UserWrapper) dataService.createUser(BigInteger.valueOf(1));
tx.success();
}
finally {
tx.finish();
}
}
答案 1 :(得分:0)
我从迈克尔的回答中间接找到了这个问题的答案。我意识到使用assertNotNull(userNode2);如果它直接在dataService.createUser()之后但是如果它在try finally块之后传递则失败。因此,如果我想使用我创建的节点,我需要在创建节点使用它之后创建另一个try finally块。我相信这是因为在调用tx.success()之前不会将用户添加到索引中,尽管这只是猜测。