Testing strings
When the property is a string type, you can filter by the starting characters in the string:
MATCH (m:Movie)
WHERE m.title STARTS WITH 'Toy Story'
RETURN m.title, m.released
This query returns the four title and released dates for all movies whose title begins with Toy Story.
And you can filter queries whose properties end with a set of characters:
MATCH (m:Movie)
WHERE m.title ENDS WITH ' I'
RETURN m.title, m.released
This query returns five rows that meet the filtering criteria.
Additionally, you can test if a substring is contained in a property:
MATCH (m:Movie)
WHERE m.title CONTAINS 'River'
RETURN m.title, m.released
Case-sensitive strings
String matching in Cypher is case-sensitive. If string values could be mis-interpreted if the letters do not match in case, your queries may miss data in the graph. For example, the user may enter a mixed-case value, emil@Neo4j.com, which is not the same for matching purposes to emil@neo4j.com.
Here is an example query where case is significant:
MATCH (p:Person)
WHERE toLower(p.name) ENDS WITH 'demille'
RETURN p.name
We do not know if the data in the graph for a name is DeMille, Demille, or deMlle. To ensure we match all Person nodes that could be one of these, we transform the property value to lower-case, so we can perform the test. This query returns one name, Cecille B. DeMille.
Conversely, we can do the same test with upper-case:
MATCH (p:Person)
WHERE toUpper(p.name) ENDS WITH 'DEMILLE'
RETURN p.name
This query returns the same name.
Here is an example using CONTAINS
:
MATCH (p:Person)
WHERE toUpper(p.name) CONTAINS ' DE '
RETURN p.name
In this query, we find all people that have " de", " De", or " DE" in their names.
About indexes for queries
If you transform a string property during a query, such as toUpper() or toLower(), the query engine turns off the use of the index.
With any query, you can always check if an index will be used by prefixing the query with EXPLAIN.
EXPLAIN MATCH (m:Movie)
WHERE m.title STARTS WITH 'Toy Story'
RETURN m.title, m.released
This query produces the execution plan where the first step is NodeIndexSeekByRange. In this case an index will be used because it is defined in the graph.
But with this query the index will not be used, even if present in the graph, because toLower() is used:
EXPLAIN MATCH (p:Person)
WHERE toLower(p.name) ENDS WITH 'demille'
RETURN p.name
A best practice for handling property values that need to be evaluated as upper, lower, or mixed case is to use fulltext schema indexes.
Managing indexes is beyond the scope of this course, but you can read about indexes in the Neo4j Cypher Manual.
In addition, you can take the course Cypher Indexes and Constraints.
Check your understanding
1. Testing a string property
We want to find all actors whose name begins with Robert. What clause do you use?
Once you have selected your option, click the Check Results query button to continue.
MATCH (p:Person)
/*select:WHERE p.name STARTS WITH 'Robert'*/
RETURN p.name
-
❏
WHERE p.name CONTAINS 'Robert'
-
❏
WHERE p.name BEGINS 'Robert'
-
✓
WHERE p.name STARTS WITH 'Robert'
-
❏
WHERE p.name >= 'Robert'
Hint
The test must be specifically for the beginning of the property value. What Cypher keyword do you test the beginning of a string property with?
Solution
WHERE p.name STARTS WITH 'Robert'
is the correct answer.
CONTAINS
will test if the string is anywhere in the property value.
>=
is used for string comparison, but would not test for "Robert" at the beginning of the string.
There is no such keyword BEGINS
in Cypher.
2. Will the index be used?
What Cypher keyword can you use to determine if an index will be used for a query?
-
✓
EXPLAIN
-
❏
PLAN
-
❏
SHOW INDEX
-
❏
CHECK INDEX
Hint
This keyword is specified as the first keyword in your query. It does not execute the query, but simply shows the query plan.
Solution
EXPLAIN
is the correct answer. It does not execute the query, but does return the query plan that will show if an index will be used.
All of the other possible answers are not valid Cypher keywords.
Summary
In this lesson, you reviewed and learned about filtering string values in queries.
In the next challenge, you will write queries to filter data string data.