diff --git a/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc b/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc index 7f1c67267..2888e8d03 100644 --- a/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc +++ b/modules/ROOT/pages/indexes/search-performance-indexes/using-indexes.adoc @@ -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) @@ -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 @@ -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. @@ -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) @@ -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. @@ -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) @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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 @@ -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