1515from __future__ import annotations
1616
1717import logging
18+ import warnings
1819from typing import List , Literal , Optional
1920
2021import neo4j
2324from neo4j_graphrag .neo4j_queries import (
2425 UPSERT_VECTOR_ON_NODE_QUERY ,
2526 UPSERT_VECTOR_ON_RELATIONSHIP_QUERY ,
27+ UPSERT_VECTORS_ON_NODE_QUERY ,
28+ UPSERT_VECTORS_ON_RELATIONSHIP_QUERY ,
2629)
2730
2831from .exceptions import Neo4jIndexError , Neo4jInsertionError
29- from .types import FulltextIndexModel , VectorIndexModel
32+ from .types import EntityType , FulltextIndexModel , VectorIndexModel
3033
3134logger = logging .getLogger (__name__ )
3235
@@ -245,6 +248,86 @@ def drop_index_if_exists(
245248 raise Neo4jIndexError (f"Dropping Neo4j index failed: { e .message } " ) from e
246249
247250
251+ def upsert_vectors (
252+ driver : neo4j .Driver ,
253+ ids : List [str ],
254+ embedding_property : str ,
255+ embeddings : List [List [float ]],
256+ neo4j_database : Optional [str ] = None ,
257+ entity_type : EntityType = EntityType .NODE ,
258+ ) -> None :
259+ """
260+ This method constructs a Cypher query and executes it to upsert
261+ (insert or update) embeddings on a set of nodes or relationships.
262+
263+ Example:
264+
265+ .. code-block:: python
266+
267+ from neo4j import GraphDatabase
268+ from neo4j_graphrag.indexes import upsert_vectors
269+
270+ URI = "neo4j://localhost:7687"
271+ AUTH = ("neo4j", "password")
272+
273+ # Connect to Neo4j database
274+ driver = GraphDatabase.driver(URI, auth=AUTH)
275+
276+ # Upsert embeddings data for several nodes
277+ upsert_vectors(
278+ driver,
279+ ids=['123', '456', '789'],
280+ embedding_property="vectorProperty",
281+ embeddings=[
282+ [0.12, 0.34, 0.56],
283+ [0.78, 0.90, 0.12],
284+ [0.34, 0.56, 0.78],
285+ ],
286+ neo4j_database="neo4j",
287+ entity_type='NODE',
288+ )
289+
290+ Args:
291+ driver (neo4j.Driver): Neo4j Python driver instance.
292+ ids (List[int]): The element IDs of the nodes or relationships.
293+ embedding_property (str): The name of the property to store the vectors in.
294+ embeddings (List[List[float]]): The list of vectors to store, one per ID.
295+ neo4j_database (Optional[str]): The name of the Neo4j database.
296+ If not provided, defaults to the server's default database. 'neo4j' by default.
297+ entity_type (EntityType): Specifies whether to upsert to nodes ('NODE') or relationships ('RELATIONSHIP').
298+ Defaults to 'NODE'.
299+
300+ Raises:
301+ ValueError: If the lengths of IDs and embeddings do not match, or if embeddings are not of uniform dimension.
302+ Neo4jInsertionError: If an error occurs while attempting to upsert the vectors in Neo4j.
303+ """
304+ if entity_type == EntityType .NODE :
305+ query = UPSERT_VECTORS_ON_NODE_QUERY
306+ elif entity_type == EntityType .RELATIONSHIP :
307+ query = UPSERT_VECTORS_ON_RELATIONSHIP_QUERY
308+ else :
309+ raise ValueError ("entity_type must be either 'NODE' or 'RELATIONSHIP'" )
310+ if len (ids ) != len (embeddings ):
311+ raise ValueError ("ids and embeddings must be the same length" )
312+ if not all (len (embedding ) == len (embeddings [0 ]) for embedding in embeddings ):
313+ raise ValueError ("All embeddings must be of the same size" )
314+ try :
315+ parameters = {
316+ "rows" : [
317+ {"id" : id , "embedding" : embedding }
318+ for id , embedding in zip (ids , embeddings )
319+ ],
320+ "embedding_property" : embedding_property ,
321+ }
322+ driver .execute_query (
323+ query_ = query , parameters_ = parameters , database_ = neo4j_database
324+ )
325+ except neo4j .exceptions .ClientError as e :
326+ raise Neo4jInsertionError (
327+ f"Upserting vectors to Neo4j failed: { e .message } "
328+ ) from e
329+
330+
248331def upsert_vector (
249332 driver : neo4j .Driver ,
250333 node_id : int ,
@@ -253,6 +336,9 @@ def upsert_vector(
253336 neo4j_database : Optional [str ] = None ,
254337) -> None :
255338 """
339+ .. warning::
340+ 'upsert_vector' is deprecated and will be removed in a future version, please use 'upsert_vectors' instead.
341+
256342 This method constructs a Cypher query and executes it to upsert (insert or update) a vector property on a specific node.
257343
258344 Example:
@@ -286,6 +372,11 @@ def upsert_vector(
286372 Raises:
287373 Neo4jInsertionError: If upserting of the vector fails.
288374 """
375+ warnings .warn (
376+ "'upsert_vector' is deprecated and will be removed in a future version, please use 'upsert_vectors' instead." ,
377+ DeprecationWarning ,
378+ stacklevel = 2 ,
379+ )
289380 try :
290381 parameters = {
291382 "node_element_id" : node_id ,
@@ -309,6 +400,9 @@ def upsert_vector_on_relationship(
309400 neo4j_database : Optional [str ] = None ,
310401) -> None :
311402 """
403+ .. warning::
404+ 'upsert_vector_on_relationship' is deprecated and will be removed in a future version, please use 'upsert_vectors' instead.
405+
312406 This method constructs a Cypher query and executes it to upsert (insert or update) a vector property on a specific relationship.
313407
314408 Example:
@@ -342,6 +436,11 @@ def upsert_vector_on_relationship(
342436 Raises:
343437 Neo4jInsertionError: If upserting of the vector fails.
344438 """
439+ warnings .warn (
440+ "'upsert_vector_on_relationship' is deprecated and will be removed in a future version, please use 'upsert_vectors' instead." ,
441+ DeprecationWarning ,
442+ stacklevel = 2 ,
443+ )
345444 try :
346445 parameters = {
347446 "rel_element_id" : rel_id ,
@@ -365,6 +464,9 @@ async def async_upsert_vector(
365464 neo4j_database : Optional [str ] = None ,
366465) -> None :
367466 """
467+ .. warning::
468+ 'async_upsert_vector' is deprecated and will be removed in a future version.
469+
368470 This method constructs a Cypher query and asynchronously executes it
369471 to upsert (insert or update) a vector property on a specific node.
370472
@@ -399,6 +501,11 @@ async def async_upsert_vector(
399501 Raises:
400502 Neo4jInsertionError: If upserting of the vector fails.
401503 """
504+ warnings .warn (
505+ "'async_upsert_vector' is deprecated and will be removed in a future version." ,
506+ DeprecationWarning ,
507+ stacklevel = 2 ,
508+ )
402509 try :
403510 parameters = {
404511 "node_id" : node_id ,
@@ -422,6 +529,9 @@ async def async_upsert_vector_on_relationship(
422529 neo4j_database : Optional [str ] = None ,
423530) -> None :
424531 """
532+ .. warning::
533+ 'async_upsert_vector_on_relationship' is deprecated and will be removed in a future version.
534+
425535 This method constructs a Cypher query and asynchronously executes it
426536 to upsert (insert or update) a vector property on a specific relationship.
427537
@@ -456,6 +566,11 @@ async def async_upsert_vector_on_relationship(
456566 Raises:
457567 Neo4jInsertionError: If upserting of the vector fails.
458568 """
569+ warnings .warn (
570+ "'async_upsert_vector_on_relationship' is deprecated and will be removed in a future version." ,
571+ DeprecationWarning ,
572+ stacklevel = 2 ,
573+ )
459574 try :
460575 parameters = {
461576 "rel_id" : rel_id ,
0 commit comments