SEARCHCypher 25 onlyIntroduced in Neo4j 2026.01
|
Preview Feature
The vector search feature is offered AS-IS as described in your agreement with Neo4j and should only be used for internal development purposes. When this feature becomes generally available, you will need to upgrade to the latest Neo4j version (which may require downtime) to use the feature for non-development purposes. Vector search is enabled by default, both in Aura and self-managed Neo4j. During the Preview period, if you have any feedback, comments, or encounter any issues, we welcome them in our public GitHub repository.
We will address them to the best of our ability.
Please include the term Vector search in the title of your issue so we can identify it more easily. |
The SEARCH clause is not a clause in its own right — rather, it is a subclause used within MATCH and OPTIONAL MATCH clauses to add constraints on their pattern based on approximate nearest neighbor (ANN) vector search.
In order to use the SEARCH clause, you must first have created a vector index.
SEARCH clause syntax
The SEARCH clause has the following syntax
[OPTIONAL] MATCH pattern
SEARCH binding_variable IN (
VECTOR INDEX index_name
FOR query_vector
[WHERE ...]
LIMIT top_k
) [SCORE AS score_alias]
The SEARCH clause constrains the pattern from the enclosing MATCH or OPTIONAL MATCH, by only returning nodes or relationships included in the results of the ANN vector search as described by the SEARCH clause.
Below follows a short description of the different parts of the syntax:
-
The
binding_variablemust be a node or relationship variable from thepatternof the enclosingMATCHorOPTIONAL MATCHclause. -
The
index_namemust be an identifier that matches the name of an existing vector index in the Neo4j database. The vector index must be a node vector index if thebinding_variablerefers to a node and a relationship vector index if thebinding_variablerefers to a relationship. -
The
query_vectorcan be any expression that evaluates to aVECTORorLIST<INTEGER NOT NULL | FLOAT NOT NULL>, for example a literal, a parameter or a property. TheSEARCHclause returns a neighborhood of nodes or relationships based on the similarity between thequery_vectorthe corresponding property of those nodes or relationships. -
The optional
WHEREsubclause applies a filter to the vector index, and is a restricted version of the normal Cypher®WHEREclause. For more information, see Predicates for vector search with filters. -
The
LIMITclause sets the number of approximate nearest neighbor nodes or relationships returned by theSEARCHclause. Thetop_kmust be of typeINTEGER NOT NULLand in the interval0 <= top_k <= 2147483647[1]. -
The optional
SCOREsubclause makes theSEARCHclause return the similarity score for each node or relationship in addition to the node or relationship itself. In the result, the column for the similarity scores will be calledscore_alias. -
The
SEARCHclause puts some restrictions on whichpatternthe enclosingMATCHorOPTIONAL MATCHclause is allowed to have. For more information, see Limitations of theSEARCHclause.
Example graph and vector index
The following graph is used for the examples below:
To recreate the graph, run the following query in an empty Neo4j database:
CREATE (:Movie {title: 'Aladdin', releaseDate: date('1992-11-08'), rating: 8.0}),
(:Movie {title: 'Cinderella', embedding: vector([1, 3, 4], 3, INTEGER), releaseDate: date('1950-02-15'), rating: 7.3}),
(:Movie:Favorite {title: 'Frozen', embedding: [1, 3, 3], releaseDate: date('2013-11-10'), rating: 7.4}),
(:Movie {title: 'Lilo & Stitch', embedding: vector([1, 1, 3], 3, INTEGER), releaseDate: date('2002-06-16'), rating: 7.4}),
(:Movie:Favorite {title: 'Lion King', embedding: vector([2, 5, 2], 3, INTEGER), releaseDate: date('1994-06-12'), rating: 8.5}),
(:Movie:Favorite {title: 'Mulan', embedding: [2, 3, 3], releaseDate: date('1998-06-05'), rating: 7.7}),
(:Movie {title: 'Snow White', embedding: vector([1, 2, 3], 3, INTEGER), releaseDate: date('1937-12-21'), rating: 7.6})
Each node in the example graph represents a movie with properties for its title, release date and rating.
The majority of the nodes also have a VECTOR property called embedding, which is a vector representation of the plot of the movie.
In a real-world example, these vector embeddings would typically be generated by a proprietary or open source embedding generator and have a dimension of for example 768 or 1536, but for simplicity this example dataset uses vector embeddings of dimension 3.
The examples use a vector index named moviePlots on the embedding property and releaseDate and rating as additional properties for filtering.
Such a vector index can be created with the following Cypher query:
CREATE VECTOR INDEX moviePlots IF NOT EXISTS
FOR (m:Movie) ON m.embedding
WITH [m.releaseDate, m.rating]
OPTIONS {
indexConfig: {
`vector.similarity_function`: 'cosine',
`vector.dimensions`: 3,
`vector.quantization.enabled`: false
}
}
For more information about the creation of vector indexes, see Create vector indexes.
Basic vector search
Find the most similar nodes
In our example dataset, the movie with the title Snow White has the embedding vector([1, 2, 3], 3, INTEGER).
To find the 4 most similar movies to Snow White, you can run several different Cypher queries with the SEARCH clause.
MATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR vector([1, 2, 3], 3, INTEGER)
LIMIT 4
)
RETURN movie.title AS title
| title |
|---|
|
|
|
|
|
MATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR [1, 2, 3]
LIMIT 4
)
RETURN movie.title AS title
| title |
|---|
|
|
|
|
|
{
"snowWhiteEmbedding": vector([1, 2, 3], 3, INTEGER)
}
MATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR $snowWhiteEmbedding
LIMIT 4
)
RETURN movie.title AS title
| title |
|---|
|
|
|
|
|
MATCH (snowWhite:Movie {title: 'Snow White'})
MATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR snowWhite.embedding
LIMIT 4
)
RETURN movie.title AS title
| title |
|---|
|
|
|
|
|
All four queries above return the same result.
The movie nodes are returned in decreasing similarity order.
Snow White is the most similar movie to itself, while Mulan is the fourth most similar movie to Snow White.
The movies Lilo & Stitch and Lion King are not returned as they are not among the top 4 most similar movies, while the movie Aladdin does not have an embedding property and is therefore not considered by the vector index at all.
|
The label predicate |
Find the most similar nodes with score
To return the four most similar movies to Snow White together with their similarity score, you can include the optional SCORE subclause in the SEARCH clause.
MATCH (snowWhite:Movie {title: 'Snow White'})
MATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR snowWhite.embedding
LIMIT 4
) SCORE AS similarityScore
RETURN movie.title AS title, similarityScore
| title | similarityScore |
|---|---|
|
|
|
|
|
|
|
|
|
|
Similarity scores have type FLOAT NOT NULL and are bounded between 0.0 and 1.0.
The closer to 1.0 the score is, the more similar the indexed embedding property is to the query vector.
The movie Snow White has a similarity score of 1.0 as its embedding property is identical to the query vector.
Similarity scores are calculated using the similarity function that was chosen when the vector index was created, the default is cosine similarity. For more information on similarity functions, see Cosine and Euclidean similarity functions.
Additional predicates in the MATCH pattern
The pattern in the MATCH or OPTIONAL MATCH can have label and property predicates on the node or relationship with the binding variable.
MATCH (movie:Movie&Favorite)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR vector([1, 2, 3], 3, INTEGER)
LIMIT 4
)
RETURN movie.title AS title
| title |
|---|
|
|
|
|
The label predicate acts as a post-filtering step to the vector search.
Even if the movie node with the title |
MATCH (movie:Movie {releaseDate: date('2013-11-10')})
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR vector([1, 2, 3], 3, INTEGER)
LIMIT 4
)
RETURN movie.title AS title
| title |
|---|
|
|
Vector search with filters
A MATCH or OPTIONAL MATCH clause can have both a WHERE subclause and SEARCH subclause.
Regardless of their order, the WHERE clause will act as a post-filtering step to the vector search, further filtering down the results.
Either of the queries below find the four most similar movies to Snow White and then filter down the result to only movies which were released after 1990.
MATCH (movie:Movie)
WHERE movie.releaseDate > date('1990')
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR vector([1, 2, 3], 3, INTEGER)
LIMIT 4
)
RETURN movie.title AS title, movie.releaseDate.year AS year
MATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR vector([1, 2, 3], 3, INTEGER)
LIMIT 4
)
WHERE movie.releaseDate > date('1990')
RETURN movie.title AS title, movie.releaseDate.year AS year
| title | year |
|---|---|
|
|
|
|
|
|
Often, it is preferable to do the filtering while performing the vector search, so called in-index filtering, instead of as a post-filtering step.
This can be achieved with vector search with filters, where the WHERE is a subclause to the SEARCH clause instead of a subclause to the enclosing MATCH or OPTIONAL MATCH clause.
To find the four most similar movies to Snow White which were released after 1990 with a vector search with filters, use the following query.
MATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR vector([1, 2, 3], 3, INTEGER)
WHERE movie.releaseDate > date('1990')
LIMIT 4
)
RETURN movie.title AS title, movie.releaseDate.year AS year
| title | year |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
When using vector search with filters, the vector search continues until it has found the requested number of result that also fulfills the other predicates.
By contrast, using a normal |
Combining vector search with filters and post-filtering
Vector search with filters and a normal WHERE clause can be combined.
The following query finds the four most similar movies to Snow White which were released after 1990, and then does post-filtering to discard any result with a rating worse than 7.5.
WHERE clauseMATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR vector([1, 2, 3], 3, INTEGER)
WHERE movie.releaseDate > date('1990')
LIMIT 4
)
WHERE movie.rating > 7.5
RETURN movie.title AS title, movie.releaseDate.year AS year, movie.rating AS rating
| title | year | rating |
|---|---|---|
|
|
|
|
|
|
|
||
Predicates for vector search with filters
The optional WHERE subclause used to do vector search with filters is a restricted version of the normal Cypher WHERE clause and only allows certain types of predicates.
The predicate must be a property predicate or several property predicates with AND between them.
MATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR vector([1, 2, 3], 3, INTEGER)
WHERE movie.releaseDate > date('1948') AND date('2010') > movie.releaseDate
LIMIT 4
)
RETURN movie.title AS title, movie.releaseDate.year AS year
| title | year |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
The |
MATCH (snowWhite:Movie {title:"Snow White"})
MATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR snowWhite.embedding
WHERE movie.releaseDate < date('2000') AND movie.rating >= snowWhite.rating
LIMIT 4
)
RETURN movie.title AS title, movie.releaseDate.year AS year, movie.rating AS rating
| title | year | rating |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
||
|
If the |
The variable in the property predicate must be the same as the binding variable in the SEARCH clause.
MATCH (m: Movie {name: "Snow White"})
MATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR vector([1, 2, 3], 3, INTEGER)
WHERE m.rating > 8
LIMIT 4
)
RETURN movie.title AS title
The variable `m` in a vector search filter property predicate must be the same as the search clause binding variable `movie`.
All properties in the property predicate must have been added as additional properties for filtering when creating the vector index.
MATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR vector([1, 2, 3], 3, INTEGER)
WHERE movie.rating > 8 AND movie.title > "L"
LIMIT 4
)
RETURN movie.title AS title, movie.rating AS rating
22ND3: The property `title` has not been added as an additional property for the vector index `moviePlots`.
For further limitations on the WHERE predicate, see Limitations of the WHERE predicate.
More on vector search
Using a query vector with different dimensions
If the query vector has a different dimension than the configured dimension of the vector index, the query will fail.
MATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR vector([1, 2], 2, INTEGER)
LIMIT 4
)
RETURN movie.title AS title
Vector index 'moviePlots' has a configured dimensionality of 3, but the provided vector has dimension 2.
|
If the vector index has no configured dimension, the query succeeds. However, if there are no vectors in the index of the same dimension as the query vector, the result of the query will be empty. |
Using a query vector which evaluates to null
If the query vector evaluates to null, for example because it refers to a non-existing property, a SEARCH clause inside a MATCH returns no results.
MATCH (snowWhite:Movie {title: 'Snow White'})
MATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR snowWhite.prop
LIMIT 4
)
RETURN movie.title AS title
| title |
|---|
|
If the SEARCH clause with a query vector evaluating to null is instead in an OPTIONAL MATCH clause, it returns null as per regular OPTIONAL MATCH semantics.
MATCH (snowWhite:Movie {title: 'Snow White'})
OPTIONAL MATCH (movie:Movie)
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR snowWhite.prop
LIMIT 4
)
RETURN movie.title AS title
| title |
|---|
|
|
Using a binding variable which is not from the enclosing clause
The binding variable in a SEARCH clause must be a node or relationship variable from the pattern of the enclosing MATCH or OPTIONAL MATCH clause.
Trying to refer to a variable from an earlier clause in the query or introducing a new variable will cause the query to fail.
MATCH (movie:Movie)
MATCH (m: Movie {name: 'Snow White'})
SEARCH movie IN (
VECTOR INDEX moviePlots
FOR m.embedding
LIMIT 4
)
RETURN movie.title AS title
The variable `movie` in SEARCH must reference a variable from the same MATCH statement.
MATCH (movie:Movie)
SEARCH node IN (
VECTOR INDEX moviePlots
FOR vector([1, 2, 3], 3, INTEGER)
LIMIT 4
)
RETURN movie.title AS title
Variable `node` not defined
Limitations of the SEARCH clause
The tables below list some past and current limitations of the SEARCH clause.
If applicable, the version which lifted the limitation is also listed.
The SEARCH clause puts restrictions on the pattern of the enclosing MATCH or OPTIONAL MATCH clause.
| Limitation | Disallowed example | Lifted in |
|---|---|---|
The pattern cannot have more than one bound variable. |
|
|
The pattern cannot have predicates on other elements than the bound variable. |
|
|
The pattern cannot have a length longer than one relationship hop. |
|
|
The pattern cannot have multiple pattern parts. |
|
|
The pattern cannot have a path selector other than |
|
The optional WHERE subclause used to do vector search with filters is a restricted version of the normal Cypher WHERE clause and only allows certain types of property predicates.
| Limitation | Disallowed example | Lifted in |
|---|---|---|
The comparison operator in the predicate cannot be |
|
|
The comparison operator in the predicate cannot be |
|
Neo4j 2026.02 |
The comparison operator in the predicate cannot be |
|
|
The predicate cannot include other boolean operators than |
|
|
The predicate cannot include a list operator. |
|
|
The predicate cannot include a string operator. |
|
|
The predicate cannot include a type predicate expression. |
|
|
The expression in the predicate cannot be of type |
|
|
The expression in the predicate cannot be of type |
|
|
The expression in the predicate cannot be of type |
|
|
The expression in the predicate is not allowed to reference the binding variable. |
|
|
The predicate cannot contain multiple property predicates on the same property in the same direction. |
|
|
The predicate cannot contain multiple property predicates on the same property where one is an equality and one is a range predicate. |
|
|
2. NOT is allowed for boolean properties. For example, given that seen has been added as an additional property for filtering when the vector index was created, WHERE NOT movie.seen is allowed and will be rewritten to WHERE movie.seen = false internally.
| ||
| Limitation | Lifted in |
|---|---|
Unlike in other index commands such as |
|
The query vector is not allowed to reference the binding variable.
Error message
|
Integer.MAX_VALUE from Java