0

私が遭遇している問題は、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());
}
4

2 に答える 2

2

2番目のユーザーをどこに追加しますか?テストを2回実行することによって?次にImpermanentGraphDatabase、2回目の実行の前に、すべてのデータを(テスト用に)削除します。インデックス作成はコミット時に行われ、トランザクション中のすべての変更を集約します。そのため、tx(userNode2)内にインデックスが表示されません。必要に応じて、このチェックをテストに追加できます(以下を参照)。

あなたのコードから、あなたがどこを呼んでも見えません、あなたinitIndicesは場所を示してもらえますか?また、自動インデクサーが正しいプロパティにインデックスを付けていることを確認してください。

テストをに変更してみてください。そうすると、2番目の呼び出しで例外がスローされます。

@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();
    }
}
于 2011-11-06T23:54:45.907 に答える
0

私はマイケルの答えから間接的にこの質問への答えを見つけました。assertNotNull(userNode2);を使用していることに気づきました。dataService.createUser()の直後の場合は失敗しましたが、tryfinallyブロックの直後の場合は合格しました。したがって、作成したノードを使用する場合は、これを使用するノードを作成したノードの後に​​、別のtryfinallyブロックを作成する必要があります。これは、tx.success()が呼び出されるまでユーザーがインデックスに追加されないためだと思いますが、これは単なる推測です。

于 2011-11-07T19:14:39.473 に答える