14.1. Indexes

A database index is a redundant copy of information in the database for the purpose of making retrieving said data more efficient. This comes at the cost of additional storage space and slower writes, so deciding what to index and what not to index is an important and often non-trivial task.

Cypher allows the creation of indexes over a property for all nodes that have a given label. Once an index has been created, it will automatically be managed and kept up to date by the database whenever the graph is changed. Neo4j will automatically pick up and start using the index once it has been created and brought online.

Create an index

To create an index on a property for all nodes that have a label, use CREATE INDEX ON. Note that the index is not immediately available, but will be created in the background.

Query 

CREATE INDEX ON :Person(name)

Result

(empty result)

Drop an index

To drop an index on all nodes that have a label and property combination, use the DROP INDEX clause.

Query 

DROP INDEX ON :Person(name)

Result

Indexes removed: 1

(empty result)

Use index

There is usually no need to specify which indexes to use in a query, Cypher will figure that out by itself. For example the query below will use the Person(name) index, if it exists. If you want Cypher to use specific indexes, you can enforce it using hints. See Section 10.8, “Using”.

Query 

MATCH (person:Person { name: 'Andres' })
RETURN person

Query Plan 

+-----------------+----------------+------+---------+-------------+---------------+
| Operator        | Estimated Rows | Rows | DB Hits | Identifiers | Other         |
+-----------------+----------------+------+---------+-------------+---------------+
| +ProduceResults |              1 |    1 |       0 | person      | person        |
| |               +----------------+------+---------+-------------+---------------+
| +NodeIndexSeek  |              1 |    1 |       2 | person      | :Person(name) |
+-----------------+----------------+------+---------+-------------+---------------+

Total database accesses: 2

Use index with WHERE using equality

Indexes are also automatically used for equality comparisons of an indexed property in the WHERE clause. If you want Cypher to use specific indexes, you can enforce it using hints. See Section 10.8, “Using”.

Query 

MATCH (person:Person)
WHERE person.name = 'Andres'
RETURN person

Query Plan 

+-----------------+----------------+------+---------+-------------+---------------+
| Operator        | Estimated Rows | Rows | DB Hits | Identifiers | Other         |
+-----------------+----------------+------+---------+-------------+---------------+
| +ProduceResults |              1 |    1 |       0 | person      | person        |
| |               +----------------+------+---------+-------------+---------------+
| +NodeIndexSeek  |              1 |    1 |       2 | person      | :Person(name) |
+-----------------+----------------+------+---------+-------------+---------------+

Total database accesses: 2

Use index with WHERE using inequality

Indexes are also automatically used for inequality (range) comparisons of an indexed property in the WHERE clause. If you want Cypher to use specific indexes, you can enforce it using hints. See Section 10.8, “Using”.

Query 

MATCH (person:Person)
WHERE person.name > 'B'
RETURN person

Query Plan 

+-----------------------+----------------+------+---------+-------------+---------------------------------+
| Operator              | Estimated Rows | Rows | DB Hits | Identifiers | Other                           |
+-----------------------+----------------+------+---------+-------------+---------------------------------+
| +ProduceResults       |             33 |    1 |       0 | person      | person                          |
| |                     +----------------+------+---------+-------------+---------------------------------+
| +NodeIndexSeekByRange |             33 |    1 |       2 | person      | :Person(name) > {  AUTOSTRING0} |
+-----------------------+----------------+------+---------+-------------+---------------------------------+

Total database accesses: 2

Use index with IN

The IN predicate on person.name in the following query will use the Person(name) index, if it exists. If you want Cypher to use specific indexes, you can enforce it using hints. See Section 10.8, “Using”.

Query 

MATCH (person:Person)
WHERE person.name IN ['Andres', 'Mark']
RETURN person

Query Plan 

+-----------------+----------------+------+---------+-------------+---------------+
| Operator        | Estimated Rows | Rows | DB Hits | Identifiers | Other         |
+-----------------+----------------+------+---------+-------------+---------------+
| +ProduceResults |              2 |    2 |       0 | person      | person        |
| |               +----------------+------+---------+-------------+---------------+
| +NodeIndexSeek  |              2 |    2 |       4 | person      | :Person(name) |
+-----------------+----------------+------+---------+-------------+---------------+

Total database accesses: 4

include::use-index-when-checking-for-the-existence-of-a-property.asciidoc[]