Skip to content

Commit acc02f5

Browse files
authored
Merge pull request #139 from neo4j/vector-index-search
Vector index search directives
2 parents 8f18b3d + aba3a4f commit acc02f5

File tree

3 files changed

+195
-3
lines changed

3 files changed

+195
-3
lines changed

modules/ROOT/pages/directives/index.adoc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,12 +105,15 @@ Particularly useful for types that are not correctly pluralized or are non-Engli
105105
|===
106106
| Directive | Description
107107

108-
| xref::/directives/indexes-and-constraints.adoc#type-definitions-indexes-fulltext[`@fulltext`]
108+
| xref::/directives/indexes-and-constraints.adoc#_fulltext_indexes[`@fulltext`]
109109
| Indicates that there should be a fulltext index inserted into the database for the specified Node and its properties.
110110

111-
| xref::/directives/indexes-and-constraints.adoc#type-definitions-constraints-unique[`@unique`]
111+
| xref::/directives/indexes-and-constraints.adoc#_unique_node_property_constraints[`@unique`]
112112
| Indicates that there should be a uniqueness constraint in the database for the fields that it is applied to.
113113

114+
| xref::/directives/indexes-and-constraints.adoc#_vector_index_search[`@vector`]
115+
| Perform a vector index search on your database either based by passing in a vector index or a search phrase. label:beta[]
116+
114117
|===
115118

116119
== Custom logic

modules/ROOT/pages/directives/indexes-and-constraints.adoc

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,191 @@ const schema = await neoSchema.getSchema();
247247
248248
await neoSchema.assertIndexesAndConstraints({ options: { create: true }});
249249
----
250+
251+
252+
:description: Directives related to generative AI in the Neo4j GraphQL Library.
253+
254+
[role=label--beta]
255+
== Vector index search
256+
257+
With the `@vector` GraphQL directive you can query your database to perform a vector index search.
258+
Queries are performed by passing in either a vector index or a query phrase.
259+
260+
A query by vector index finds nodes with a vector embedding similar to that index.
261+
That is, the query performs a nearest neighbor search.
262+
263+
In contrast, a query by phrase (a string of text) forwards the phrase to the link:https://neo4j.com/docs/cypher-manual/current/genai-integrations/[Neo4j GenAI plugin] and the plugin generates a vector embedding for it.
264+
This embedding is then compared to the node vector embeddings in the database.
265+
266+
[NOTE]
267+
.Prerequisites
268+
====
269+
* The database must be Neo4j version 5.15 or higher.
270+
* The node vector embeddings already exist in the database. See link:https://neo4j.com/docs/cypher-manual/current/indexes/semantic-indexes/vector-indexes/[Vector indexes] to learn more about vector indexes in Cypher and Neo4j.
271+
* The embeddings must have been created using the same method, that is, the same provider and model. See link:https://neo4j.com/docs/genai/tutorials/embeddings-vector-indexes/[Embeddings & Vector Indexes Tutorial] to learn about vector embeddings in Cypher and Neo4j.
272+
* Queries by vector index cannot be performed across multiple labels.
273+
* Queries by phrase require credentials for the Neo4j GenAI plugin.
274+
====
275+
276+
[NOTE]
277+
====
278+
Vector index searches are _read-only_ in the sense that the data which the queries operate on are retrieved from the database but not altered or written back to the database.
279+
====
280+
281+
282+
=== Definition
283+
284+
[source, graphql]
285+
----
286+
"""Informs @neo4j/graphql that there should be a vector index in the database, allows users to search by the index in the generated schema."""
287+
directive @vector(indexes: [VectorIndexInput]!) on OBJECT
288+
----
289+
290+
`VectorIndexInput` is defined as follows:
291+
292+
[source, graphql]
293+
----
294+
input VectorIndexInput {
295+
"""(Required) The name of the vector index."""
296+
indexName: String!
297+
"""(Required) The name of the embedding property on the node."""
298+
embeddingProperty: String!
299+
"""(Required) The name of the query."""
300+
queryName: String
301+
"""(Optional) The name of the provider."""
302+
provider: String
303+
}
304+
----
305+
306+
If the optional field `provider` is set, the type is used for a query by phrase, otherwise for a query by vector.
307+
Allowed values for the `provider` field are defined by the available link:https://neo4j.com/docs/cypher-manual/current/genai-integrations/#ai-providers[GenAI providers].
308+
309+
310+
=== Usage
311+
312+
==== Query by vector index
313+
314+
Perform a nearest neighbor search by passing a vector to find nodes with a vector embedding similar to that vector.
315+
316+
.Type definition
317+
[source, graphql]
318+
----
319+
type Product @vector(indexes: [{
320+
indexName: "productDescriptionIndex",
321+
embeddingProperty: "descriptionVector",
322+
queryName: "searchByDescription"
323+
}]) {
324+
id: ID!
325+
name: String!
326+
description: String!
327+
}
328+
----
329+
330+
This defines the query to be performed on all `Product` nodes which have a vector index named `productDescriptionIndex` for the property `descriptionVector`, implying that a vector embedding has been created for the `description` property of each node.
331+
332+
.Example query
333+
[source, graphql]
334+
----
335+
query FindSimilarProducts($vector: [Float]!) {
336+
searchByDescription(vector: $vector) {
337+
productsConnection {
338+
edges {
339+
cursor
340+
score
341+
node {
342+
id
343+
name
344+
description
345+
}
346+
}
347+
}
348+
}
349+
}
350+
----
351+
352+
The input `$vector` is a list of `FLOAT` values and should look similar to this:
353+
354+
.An example vector
355+
[source, graphql]
356+
----
357+
{
358+
"vector": [
359+
0.123456,
360+
...,
361+
0.654321,
362+
]
363+
}
364+
----
365+
366+
The query returns all `Product` nodes with a vector embedding on their `descriptionVector` property which is similar to the query argument `$vector`.
367+
368+
==== Query by phrase
369+
370+
Perform a query which utilizes the link:https://neo4j.com/docs/cypher-manual/current/genai-integrations/[Neo4j GenAI plugin] to create a vector embedding for a search phrase and then compare it to existing vector embeddings on nodes in the database.
371+
372+
[NOTE]
373+
====
374+
Requires credentials for the plugin.
375+
====
376+
377+
Ensure your provider credentials are set in the call to Neo4jGraphQL, for example:
378+
379+
.Feature configuration
380+
[source, graphql]
381+
----
382+
const neoSchema = new Neo4jGraphQL({
383+
typeDefs,
384+
driver,
385+
features: {
386+
vector: {
387+
OpenAI: {
388+
token: "my-open-ai-token",
389+
model: "text-embedding-3-small",
390+
},
391+
},
392+
},
393+
});
394+
----
395+
396+
`OpenAI` is one of the GenAI providers for generating vector embeddings.
397+
See link:https://neo4j.com/docs/cypher-manual/current/genai-integrations/#ai-providers[GenAI providers] for the full list of providers and their respective identifiers.
398+
399+
.Type definition
400+
[source, graphql]
401+
----
402+
type Product @vector(indexes: [{
403+
indexName: "productDescriptionIndex",
404+
embeddingProperty: "descriptionVector",
405+
provider: OPEN_AI, # Assuming this is configured in the server
406+
queryName: "searchByPhrase"
407+
}]) {
408+
id: ID!
409+
name: String!
410+
description: String!
411+
}
412+
----
413+
414+
This defines the query to be performed on all `Product` nodes which have a vector index named `productDescriptionIndex` for the property `descriptionVector`, implying that a vector embedding has been created for the `description` property of each node.
415+
416+
.Example query
417+
[source, graphql]
418+
----
419+
query SearchProductsByPhrase($phrase: String!) {
420+
searchByPhrase(phrase: $phrase) {
421+
productsConnection {
422+
edges {
423+
cursor
424+
score
425+
node {
426+
id
427+
name
428+
description
429+
}
430+
}
431+
}
432+
}
433+
}
434+
----
435+
436+
First, the query passes the query phrase argument `$phrase` to the GenAI plugin and lets it generate a vector embedding for the phrase.
437+
Then it returns all `Product` nodes with a vector embedding on their `descriptionVector` property which are similar to the vector embedding generated by the plugin.

modules/ROOT/pages/index.adoc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ Additionally, prerelease version numbers may have additional suffixes, for examp
6969

7070
== Requirements
7171

72-
. https://neo4j.com/[Neo4j Database] version 4.4 and newer with https://neo4j.com/docs/apoc/current/[APOC] plugin.
72+
. https://neo4j.com/[Neo4j Database] version 4.4 or newer with https://neo4j.com/docs/apoc/current/[APOC] plugin.
73+
. Neo4j version 5.15 or newer when you are using the xref:/directives/indexes-and-constraints.adoc#_vector_index_search[`@vector` directive].
7374
. https://nodejs.org/en/[Node.js] 16+.
7475

7576
== Resources

0 commit comments

Comments
 (0)