Skip to content

Commit

Permalink
minor fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
JPryce-Aklundh committed Jan 9, 2024
1 parent 7d17e4b commit 3b28307
Showing 1 changed file with 15 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ They are particularly useful for dealing with properties that have ordered, comp

The following example first creates a relevant index on the type property for `PointOfInterest` nodes, and then runs the above query again, counting the number of `PointOfInterest` nodes that have a `baseball` `type` value:

.Create range index
.Create a range index
[source,cypher]
----
CREATE INDEX range_index_type FOR (n:PointOfInterest) ON (n.type)
Expand All @@ -101,7 +101,7 @@ CREATE INDEX range_index_type FOR (n:PointOfInterest) ON (n.type)
If no index type is specified when creating an index, Neo4j will default to create a range index.
For more information about creating indexes, see xref:indexes/search-performance-indexes/managing-indexes.adoc#create-indexes[Managing search-performance indexes -> CREATE INDEX].

.Rerun query
.Rerun query after the creation of a relevant index
[source,cypher]
----
PROFILE
Expand Down Expand Up @@ -130,7 +130,7 @@ Comparing this query plan with the plan generated before the creation of a relev
* NodeByLabelScan has been replaced by xref:planning-and-tuning/operators/operators-detail.adoc#query-plan-node-index-seek[NodeIndexSeek].
This only produces 26 rows (representing the 26 `PointOfInterest` nodes in the database with a `type` value set to `baseball`).
* The query now only requires 27 DB hits.
* The query completed in less than 1 milliseconds - almost 8 times faster than it took the query to complete without a range index.
* The query completed in less than 1 millisecond - almost 8 times faster than it took the query to complete without a range index.

These points all illustrate the fundamental point that search-performance indexes can significantly improve the performance of Cypher queries.

Expand All @@ -146,13 +146,13 @@ In all other cases, the range index will be used.

To show this behavior, it is necessary to create a text index and a range index on the same property:

.Create text index
.Create a text index
[source,cypher]
----
CREATE TEXT INDEX text_index_name FOR (n:PointOfInterest) ON (n.name)
----

.Create range index
.Create a range index
[source,cypher]
----
CREATE INDEX range_index_name FOR (n:PointOfInterest) ON (n.name)
Expand Down Expand Up @@ -239,7 +239,7 @@ For more information about the predicates supported by text indexes, see xref:in


[[text-index-string-size]]
=== Text indexes and STRING sizes
=== Text indexes and `STRING` sizes

The size of the indexed `STRING` properties is also relevant to the planner’s selection between range and text indexes.

Expand All @@ -258,7 +258,7 @@ Point indexes are optimized for queries filtering for the xref:functions/spatial

The following example creates a point index which is then accessed by a query that uses the `point.distance()` function to return the `name` and `type` of all `PointOfInterest` nodes within 100 meters of the `William Shakespeare` statue:

.Create point index
.Create a point index
[source,cypher]
----
CREATE POINT INDEX point_index_location FOR (n:PointOfInterest) ON (n.location)
Expand Down Expand Up @@ -487,7 +487,7 @@ CREATE INDEX composite_3 FOR (n:PointOfInterest) ON (n.name, n.type, n.lat)

Note that the order of the properties has changed: the `name` property is now the first property defined in the composite index, and the `lat` property is indexed last.

.Rerun the same query
.Rerun query after the creation of a different composite index
[source, cypher]
----
PROFILE
Expand Down Expand Up @@ -682,12 +682,12 @@ This plan shows that a separate index is used to improve the performance of each
[[indexes-and-null]]
== Indexes and `null` values

Neo4j indexes do not store `null` values.
Neo4j indexes do not store xref:values-and-types/working-with-null.adoc[`null`] values.
This means that the planner must be able to rule out the possibility of `null` values in order for queries to use an index.

The following query demonstrates the incompatibility between `null` values and indexes by counting all `PointOfInterest` nodes with an unset `name` property:

.Query count nodes with a `null` `name` value
.Query to count nodes with a `null` `name` value
[source,cypher]
----
PROFILE
Expand Down Expand Up @@ -726,7 +726,7 @@ The plan shows that neither of the two available indexes (range and text) on the
However, if a query predicate is added which is able to exclude the presence of any `null` values, then an index can be used.
The following query shows this by adding a substring predicate to the above query:

.Query count nodes with a `null` `name` value or nodes with a `name` property containing `William`
.Query to count nodes with a `null` `name` value or nodes with a `name` property containing `'William'`
[source,cypher]
----
PROFILE
Expand Down Expand Up @@ -781,7 +781,7 @@ The presence of `null` values may not be known in advance, and this can cause un
One method to ensure an index is used is to explicitly filter out any `null` values by appending `IS NOT NULL` to the queried property.
The following example uses the same query as above but exchanges `IS NULL` with `IS NOT NULL` in the `WHERE` clause:

.Query count `PointOfInterest` nodes without a `null` `name` value
.Query to count `PointOfInterest` nodes without a `null` `name` value
[source,cypher]
----
PROFILE
Expand Down Expand Up @@ -825,7 +825,7 @@ This will enforce both the existence of a property and its `STRING` type, discar

For example, if the `WHERE` predicate in the previous query is altered to instead append `IS {two-colons} STRING NOT NULL`, then the text index rather than the range index is used (range indexes do not support type predicate expressions):

.Query using type predicate expression
.Query using a type predicate expression
[source,cypher]
----
PROFILE
Expand Down Expand Up @@ -874,7 +874,7 @@ It will then run the same query with a `WHERE` predicate on the `name` property
DROP INDEX range_index_name
----

.Query count `PointOfInterest` nodes without a `null` `name` value
.Query to count `PointOfInterest` nodes without a `null` `name` value
[source,cypher]
----
PROFILE
Expand Down Expand Up @@ -912,7 +912,7 @@ CREATE CONSTRAINT type_constraint
FOR (n:PointOfInterest) REQUIRE n.name IS :: STRING
----

.Rerun the same query
.Rerun the query after the creation of a type constraint
[source,cypher]
----
PROFILE
Expand Down

0 comments on commit 3b28307

Please sign in to comment.