@@ -564,6 +564,161 @@ void getNativeClientTest() {
564564 });
565565 }
566566
567+ @ ParameterizedTest (name = "manageDocumentIds={0}" )
568+ @ ValueSource (booleans = { true , false })
569+ void testManageDocumentIdsSetting (boolean manageDocumentIds ) {
570+ getContextRunner ().run (context -> {
571+ OpenSearchVectorStore vectorStore = context .getBean ("vectorStore" , OpenSearchVectorStore .class );
572+
573+ // Create a new vector store with specific manageDocumentIds setting
574+ OpenSearchVectorStore testVectorStore = OpenSearchVectorStore
575+ .builder ((OpenSearchClient ) vectorStore .getNativeClient ().orElseThrow (),
576+ context .getBean (EmbeddingModel .class ))
577+ .manageDocumentIds (manageDocumentIds )
578+ .index ("test_manage_document_ids_" + manageDocumentIds )
579+ .initializeSchema (true )
580+ .build ();
581+
582+ // Test documents
583+ List <Document > testDocuments = List .of (new Document ("doc1" , "Test content 1" , Map .of ("key1" , "value1" )),
584+ new Document ("doc2" , "Test content 2" , Map .of ("key2" , "value2" )));
585+
586+ // Add documents
587+ testVectorStore .add (testDocuments );
588+
589+ // Wait for indexing
590+ Awaitility .await ()
591+ .until (() -> testVectorStore
592+ .similaritySearch (SearchRequest .builder ().query ("Test content" ).topK (2 ).build ()), hasSize (2 ));
593+
594+ // Search and verify results
595+ List <Document > results = testVectorStore
596+ .similaritySearch (SearchRequest .builder ().query ("Test content" ).topK (2 ).build ());
597+
598+ assertThat (results ).hasSize (2 );
599+
600+ // Verify document content and metadata are preserved
601+ assertThat (results .stream ().map (Document ::getText ).toList ()).containsExactlyInAnyOrder ("Test content 1" ,
602+ "Test content 2" );
603+
604+ assertThat (results .stream ().map (doc -> doc .getMetadata ().get ("key1" )).toList ()).contains ("value1" );
605+ assertThat (results .stream ().map (doc -> doc .getMetadata ().get ("key2" )).toList ()).contains ("value2" );
606+
607+ // Clean up
608+ testVectorStore .delete (testDocuments .stream ().map (Document ::getId ).toList ());
609+ });
610+ }
611+
612+ @ Test
613+ void testManageDocumentIdsFalseForAWSOpenSearchServerless () {
614+ getContextRunner ().run (context -> {
615+ OpenSearchVectorStore vectorStore = context .getBean ("vectorStore" , OpenSearchVectorStore .class );
616+
617+ // Create vector store with manageDocumentIds=false (AWS OpenSearch Serverless
618+ // mode)
619+ OpenSearchVectorStore awsCompatibleVectorStore = OpenSearchVectorStore
620+ .builder ((OpenSearchClient ) vectorStore .getNativeClient ().orElseThrow (),
621+ context .getBean (EmbeddingModel .class ))
622+ .manageDocumentIds (false )
623+ .index ("test_aws_serverless_compatible" )
624+ .initializeSchema (true )
625+ .build ();
626+
627+ // Test documents with IDs (these should be ignored when
628+ // manageDocumentIds=false)
629+ List <Document > testDocuments = List .of (
630+ new Document ("custom-id-1" , "AWS Serverless content 1" , Map .of ("env" , "aws-serverless" )),
631+ new Document ("custom-id-2" , "AWS Serverless content 2" , Map .of ("env" , "aws-serverless" )));
632+
633+ // Add documents - should work without explicit document ID errors
634+ awsCompatibleVectorStore .add (testDocuments );
635+
636+ // Wait for indexing
637+ Awaitility .await ()
638+ .until (() -> awsCompatibleVectorStore
639+ .similaritySearch (SearchRequest .builder ().query ("AWS Serverless" ).topK (2 ).build ()), hasSize (2 ));
640+
641+ // Search and verify results
642+ List <Document > results = awsCompatibleVectorStore
643+ .similaritySearch (SearchRequest .builder ().query ("AWS Serverless" ).topK (2 ).build ());
644+
645+ assertThat (results ).hasSize (2 );
646+
647+ // Verify content is preserved
648+ assertThat (results .stream ().map (Document ::getText ).toList ())
649+ .containsExactlyInAnyOrder ("AWS Serverless content 1" , "AWS Serverless content 2" );
650+
651+ // Verify metadata is preserved
652+ assertThat (results .stream ().map (doc -> doc .getMetadata ().get ("env" )).toList ())
653+ .containsOnly ("aws-serverless" );
654+
655+ // Clean up
656+ awsCompatibleVectorStore .delete (List .of ("_all" ));
657+ });
658+ }
659+
660+ @ Test
661+ void testManageDocumentIdsTrueWithExplicitIds () {
662+ getContextRunner ().run (context -> {
663+ OpenSearchVectorStore vectorStore = context .getBean ("vectorStore" , OpenSearchVectorStore .class );
664+
665+ // Create vector store with manageDocumentIds=true (default behavior)
666+ OpenSearchVectorStore explicitIdVectorStore = OpenSearchVectorStore
667+ .builder ((OpenSearchClient ) vectorStore .getNativeClient ().orElseThrow (),
668+ context .getBean (EmbeddingModel .class ))
669+ .manageDocumentIds (true )
670+ .index ("test_explicit_ids" )
671+ .initializeSchema (true )
672+ .build ();
673+
674+ // Test documents with specific IDs
675+ List <Document > testDocuments = List .of (
676+ new Document ("explicit-id-1" , "Explicit ID content 1" , Map .of ("type" , "explicit" )),
677+ new Document ("explicit-id-2" , "Explicit ID content 2" , Map .of ("type" , "explicit" )));
678+
679+ // Add documents
680+ explicitIdVectorStore .add (testDocuments );
681+
682+ // Wait for indexing
683+ Awaitility .await ()
684+ .until (() -> explicitIdVectorStore
685+ .similaritySearch (SearchRequest .builder ().query ("Explicit ID" ).topK (2 ).build ()), hasSize (2 ));
686+
687+ // Search and verify results
688+ List <Document > results = explicitIdVectorStore
689+ .similaritySearch (SearchRequest .builder ().query ("Explicit ID" ).topK (2 ).build ());
690+
691+ assertThat (results ).hasSize (2 );
692+
693+ // Verify document IDs are preserved
694+ assertThat (results .stream ().map (Document ::getId ).toList ()).containsExactlyInAnyOrder ("explicit-id-1" ,
695+ "explicit-id-2" );
696+
697+ // Verify content and metadata
698+ assertThat (results .stream ().map (Document ::getText ).toList ())
699+ .containsExactlyInAnyOrder ("Explicit ID content 1" , "Explicit ID content 2" );
700+
701+ assertThat (results .stream ().map (doc -> doc .getMetadata ().get ("type" )).toList ()).containsOnly ("explicit" );
702+
703+ // Test deletion by specific IDs
704+ explicitIdVectorStore .delete (List .of ("explicit-id-1" ));
705+
706+ Awaitility .await ()
707+ .until (() -> explicitIdVectorStore
708+ .similaritySearch (SearchRequest .builder ().query ("Explicit ID" ).topK (2 ).build ()), hasSize (1 ));
709+
710+ // Verify only one document remains
711+ results = explicitIdVectorStore
712+ .similaritySearch (SearchRequest .builder ().query ("Explicit ID" ).topK (2 ).build ());
713+
714+ assertThat (results ).hasSize (1 );
715+ assertThat (results .get (0 ).getId ()).isEqualTo ("explicit-id-2" );
716+
717+ // Clean up
718+ explicitIdVectorStore .delete (List .of ("explicit-id-2" ));
719+ });
720+ }
721+
567722 @ SpringBootConfiguration
568723 @ EnableAutoConfiguration (exclude = { DataSourceAutoConfiguration .class })
569724 public static class TestApplication {
0 commit comments