使用索引
可以创建并使用 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();
}
|
有关如何正确关闭索引查询返回的 |
这就是通过 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 | 您可以通过创建时指定的索引名称来查找索引。索引名称保证唯一,以确保不会误删错误的索引。 |