使用索引

可以创建和使用 Cypher 手册 → 索引 中描述的所有索引类型。

本节通过用户数据库示例演示了如何使用索引。有关如何对所有具有 username 属性的 User 节点创建索引的信息,请参阅 Cypher 手册 → 为节点创建单属性索引

此示例中使用的源代码位于:EmbeddedNeo4jWithIndexing.java

首先启动数据库服务器

DatabaseManagementService managementService = new DatabaseManagementServiceBuilder( databaseDirectory ).build();
GraphDatabaseService graphDb = managementService.database( DEFAULT_DATABASE_NAME );

然后,您可以配置数据库以按名称为用户建立索引。这只需要完成一次。

请注意,架构更改和数据更改不允许在同一事务中进行。每个事务必须要么更改架构,要么更改数据,但不能两者都更改。

IndexDefinition usernamesIndex;
try ( Transaction tx = graphDb.beginTx() )
{
    Schema schema = tx.schema();
    usernamesIndex = schema.indexFor( Label.label( "User" ) )  (1)
            .on( "username" )                                  (2)
            .withName( "usernames" )                           (3)
            .create();                                         (4)
    tx.commit();                                               (5)
}
1 单属性索引是在标签与属性名结合时定义的。通过指定节点标签开始您的索引定义。
2 接下来,定义应作为此索引一部分的属性。索引所有带有 User 标签且也具有 username 属性的节点。通过这种方式,您可以根据其 username 属性查找 User 节点。
3 索引始终有一个名称。如果未指定,它将为您自动生成。
4 调用 create 对于在数据库中创建索引定义是必需的。此索引现已创建,但它仍仅存在于您的当前事务中。
5 提交事务会将您的新索引提交到数据库。一旦它完成了用数据库中现有数据填充自身,它将变得可用。

索引在首次创建时是异步填充的。可以使用核心 API 等待索引填充完成

try ( Transaction tx = graphDb.beginTx() )
{
    Schema schema = tx.schema();
    schema.awaitIndexOnline( usernamesIndex, 10, TimeUnit.SECONDS );
}

还可以查询索引填充的进度

try ( Transaction tx = graphDb.beginTx() )
{
    Schema schema = tx.schema();
    System.out.println( String.format( "Percent complete: %1.0f%%",
        schema.getIndexPopulationProgress( usernamesIndex ).getCompletedPercentage() ) );
}

现在您可以添加用户了

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

    // Create some users
    for ( int id = 0; id < 100; id++ )
    {
        Node userNode = tx.createNode( label );
        userNode.setProperty( "username", "user" + id + "@neo4j.org" );
    }
    System.out.println( "Users created" );
    tx.commit();
}

有关如何正确关闭索引查找返回的 ResourceIterators 的信息,请阅读 资源迭代器

这是按 ID 查找用户的方法

Label label = Label.label( "User" );
int idToFind = 45;
String nameToFind = "user" + idToFind + "@neo4j.org";
try ( Transaction tx = graphDb.beginTx() )
{
    try ( ResourceIterator<Node> users =
                  tx.findNodes( label, "username", nameToFind ) )
    {
        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" ) );
        }
    }
}

当更新用户名称时,索引也会随之更新

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

    for ( Node node : loop( tx.findNodes( label, "username", nameToFind ) ) )
    {
        node.setProperty( "username", "user" + (idToFind + 1) + "@neo4j.org" );
    }
    tx.commit();
}

当删除用户时,该用户将自动从索引中移除

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

    for ( Node node : loop( tx.findNodes( label, "username", nameToFind ) ) )
    {
        node.delete();
    }
    tx.commit();
}

如果您更改数据模型,也可以删除索引

try ( Transaction tx = graphDb.beginTx() )
{
    IndexDefinition usernamesIndex = tx.schema().getIndexByName( "usernames" ); (1)
    usernamesIndex.drop();
    tx.commit();
}
1 您通过创建索引时给它的索引名称来查找索引。索引名称保证是唯一的,以确保您不会错误地找到并删除错误的索引。
© . All rights reserved.