5.4. User database with schema based indexing

You have a user database, and want to retrieve users by name using schema based indexing.

[Tip]Tip

The source code used in this example is found here: EmbeddedNeo4jWithNewIndexing.java

To begin with, we start the database server:

GraphDatabaseService graphDb = new GraphDatabaseFactory().newEmbeddedDatabase( DB_PATH );

Then we have to configure the database to index users by name. This only needs to be done once.

IndexDefinition indexDefinition;
Transaction tx = graphDb.beginTx();
try
{
    Schema schema = graphDb.schema();
    indexDefinition = schema.indexFor( DynamicLabel.label( "User" ) )
            .on( "username" )
            .create();
    tx.success();
}
finally
{
    tx.finish();
}

New indexes are populated asynchronously. It is possible to use the core API to wait for index population to complete:

Transaction transaction = graphDb.beginTx();
try
{
    Schema schema = graphDb.schema();
    schema.awaitIndexOnline( indexDefinition, 10, TimeUnit.SECONDS );
}
finally
{
    transaction.finish();
}

It’s time to add the users:

Transaction tx = graphDb.beginTx();
try
{
    Label label = DynamicLabel.label( "User" );

    // Create some users and index their names with the new
    // IndexingService
    for ( int id = 0; id < 100; id++ )
    {
        Node userNode = graphDb.createNode( label );
        userNode.setProperty( "username", "user" + id + "@neo4j.org" );
    }
    System.out.println( "Users created" );
    tx.success();
}
finally
{
    tx.finish();
}

And here’s how to find a user by id:

[Note]Note

Please read Section 5.5, “Managing resources when using long running transactions” on how to properly close ResourceIterators returned from index lookups.

Label label = DynamicLabel.label( "User" );
int idToFind = 45;
String nameToFind = "user" + idToFind + "@neo4j.org";
Transaction transaction = graphDb.beginTx();
try
{
    ResourceIterator<Node> users = graphDb.findNodesByLabelAndProperty( label, "username", nameToFind )
            .iterator();
    ArrayList<Node> userNodes = new ArrayList<>();
    while ( users.hasNext() )
    {
        userNodes.add( users.next() );
    }

    for ( Node node : userNodes )
    {
        System.out.println( "The username of user " + idToFind + " is " + node.getProperty( "username" ) );
    }
}
finally
{
    transaction.finish();
}

When updating the name of a user, the index is updated as well:

Transaction tx = graphDb.beginTx();
try
{
    Label label = DynamicLabel.label( "User" );
    int idToFind = 45;
    String nameToFind = "user" + idToFind + "@neo4j.org";

    for ( Node node : graphDb.findNodesByLabelAndProperty( label, "username", nameToFind ) )
    {
        node.setProperty( "username", "user" + ( idToFind + 1 ) + "@neo4j.org" );
    }
    tx.success();
}
finally
{
    tx.finish();
}

When deleting a user, it is automatically removed from the index:

Transaction tx = graphDb.beginTx();
try
{
    Label label = DynamicLabel.label( "User" );
    int idToFind = 46;
    String nameToFind = "user" + idToFind + "@neo4j.org";

    for ( Node node : graphDb.findNodesByLabelAndProperty( label, "username", nameToFind ) )
    {
        node.delete();
    }
    tx.success();
}
finally
{
    tx.finish();
}

In case we change our data model, we can drop the index as well:

Transaction tx = graphDb.beginTx();
try
{
    Label label = DynamicLabel.label( "User" );
    for ( IndexDefinition indexDefinition : graphDb.schema()
            .getIndexes( label ) )
    {
        // There is only one index
        indexDefinition.drop();
    }

    tx.success();
}
finally
{
    tx.finish();
}