Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Provides configuration patterns for LangChain4J vector stores in RAG applications. Use when building semantic search, integrating vector databases (PostgreSQL/pgvector, Pinecone, MongoDB, Milvus, Neo4j), implementing embedding storage/retrieval, setting up hybrid search, or optimizing vector database performance for production AI applications.
.claude/skills/giuseppe-trisciuoglio-langchain4j-vector-stores-configuration/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-15 | ✗→✓ | ▲ Improved | 38% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 87% | 0% |
| case-01 | ✗→✓ | ▲ Improved | 34% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 13% | 0% |
| case-10 | ✗→✓ | ▲ Improved | 104% | 0% |
Configure vector stores for Retrieval-Augmented Generation applications with LangChain4J.
LangChain4J provides a unified abstraction for vector stores (PostgreSQL/pgvector, Pinecone, MongoDB Atlas, Milvus, Neo4j) with builder-based configuration, metadata filtering, and hybrid search support.
Configure an embedding store for vector operations:
java@Bean public EmbeddingStore<TextSegment> embeddingStore() { return PgVectorEmbeddingStore.builder() .host("localhost") .port(5432) .database("vectordb") .user("username") .password("password") .table("embeddings") .dimension(1536) // OpenAI embedding dimension .createTable(true) .useIndex(true) .build(); }
Follow this workflow to ensure correct vector store setup:
Use different stores for different use cases:
java@Configuration public class MultiVectorStoreConfiguration { @Bean @Qualifier("documentsStore") public EmbeddingStore<TextSegment> documentsEmbeddingStore() { return PgVectorEmbeddingStore.builder() .table("document_embeddings") .dimension(1536) .build(); } @Bean @Qualifier("chatHistoryStore") public EmbeddingStore<TextSegment> chatHistoryEmbeddingStore() { return MongoDbEmbeddingStore.builder() .collectionName("chat_embeddings") .build(); } }
Use EmbeddingStoreIngestor for automated document processing:
java@Bean public EmbeddingStoreIngestor embeddingStoreIngestor( EmbeddingStore<TextSegment> embeddingStore, EmbeddingModel embeddingModel) { return EmbeddingStoreIngestor.builder() .documentSplitter(DocumentSplitters.recursive( 300, // maxSegmentSizeInTokens 20, // maxOverlapSizeInTokens new OpenAiTokenizer(GPT_3_5_TURBO) )) .embeddingModel(embeddingModel) .embeddingStore(embeddingStore) .build(); }
Configure metadata-based filtering capabilities:
java// MongoDB with metadata field mapping IndexMapping indexMapping = IndexMapping.builder() .dimension(1536) .metadataFieldNames(Set.of("category", "source", "created_date", "author")) .build(); // Search with metadata filters EmbeddingSearchRequest request = EmbeddingSearchRequest.builder() .queryEmbedding(queryEmbedding) .maxResults(10) .filter(and( metadataKey("category").isEqualTo("technical_docs"), metadataKey("created_date").isGreaterThan(LocalDate.now().minusMonths(6)) )) .build();
Implement connection pooling and monitoring:
java@Bean public EmbeddingStore<TextSegment> optimizedPgVectorStore() { HikariConfig hikariConfig = new HikariConfig(); hikariConfig.setJdbcUrl("jdbc:postgresql://localhost:5432/vectordb"); hikariConfig.setUsername("username"); hikariConfig.setPassword("password"); hikariConfig.setMaximumPoolSize(20); hikariConfig.setMinimumIdle(5); hikariConfig.setConnectionTimeout(30000); DataSource dataSource = new HikariDataSource(hikariConfig); return PgVectorEmbeddingStore.builder() .dataSource(dataSource) .table("embeddings") .dimension(1536) .useIndex(true) .build(); }
Monitor vector store connectivity:
java@Component public class VectorStoreHealthIndicator implements HealthIndicator { private final EmbeddingStore<TextSegment> embeddingStore; @Override public Health health() { try { embeddingStore.search(EmbeddingSearchRequest.builder() .queryEmbedding(new Embedding(Collections.nCopies(1536, 0.0f))) .maxResults(1) .build()); return Health.up() .withDetail("store", embeddingStore.getClass().getSimpleName()) .build(); } catch (Exception e) { return Health.down() .withDetail("error", e.getMessage()) .build(); } } }
java@Configuration public class SimpleRagConfig { @Bean public EmbeddingStore<TextSegment> embeddingStore() { return PgVectorEmbeddingStore.builder() .host("localhost") .database("rag_db") .table("documents") .dimension(1536) .build(); } @Bean public ChatLanguageModel chatModel() { return OpenAiChatModel.withApiKey(System.getenv("OPENAI_API_KEY")); } }
java@Service public class SemanticSearchService { private final EmbeddingStore<TextSegment> store; private final EmbeddingModel embeddingModel; public List<String> search(String query, int maxResults) { Embedding queryEmbedding = embeddingModel.embed(query).content(); EmbeddingSearchRequest request = EmbeddingSearchRequest.builder() .queryEmbedding(queryEmbedding) .maxResults(maxResults) .minScore(0.75) .build(); return store.search(request).matches().stream() .map(match -> match.embedded().text()) .toList(); } }
java@Configuration public class ProductionVectorStoreConfig { @Bean public EmbeddingStore<TextSegment> vectorStore( @Value("${vector.store.host}") String host, MeterRegistry meterRegistry) { EmbeddingStore<TextSegment> store = PgVectorEmbeddingStore.builder() .host(host) .database("production_vectors") .useIndex(true) .indexListSize(200) .build(); return new MonitoredEmbeddingStore<>(store, meterRegistry); } }
For Development:
InMemoryEmbeddingStore for local development and testingFor Production:
Choose index types based on performance requirements:
java// For high recall requirements .indexType(IndexType.FLAT) // Exact search, slower but accurate // For balanced performance .indexType(IndexType.IVF_FLAT) // Good balance of speed and accuracy // For high-speed approximate search .indexType(IndexType.HNSW) // Fastest, slightly less accurate
Match embedding dimensions to your model:
java// OpenAI text-embedding-3-small .dimension(1536) // OpenAI text-embedding-3-large .dimension(3072) // Sentence Transformers .dimension(384) // all-MiniLM-L6-v2 .dimension(768) // all-mpnet-base-v2
Use batch operations for better performance:
java@Service public class BatchEmbeddingService { private static final int BATCH_SIZE = 100; public void addDocumentsBatch(List<Document> documents) { for (List<Document> batch : Lists.partition(documents, BATCH_SIZE)) { List<TextSegment> segments = batch.stream() .map(doc -> TextSegment.from(doc.text(), doc.metadata())) .collect(Collectors.toList()); List<Embedding> embeddings = embeddingModel.embedAll(segments) .content(); embeddingStore.addAll(embeddings, segments); } } }
Protect sensitive configuration:
java// Use environment variables @Value("${vector.store.api.key:#{null}}") private String apiKey; // Validate configuration @PostConstruct public void validateConfiguration() { if (StringUtils.isBlank(apiKey)) { throw new IllegalStateException("Vector store API key must be configured"); } }
For comprehensive documentation and advanced configurations, see:
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-15 | fail→pass | 18,762 | 9,863 | -47% | 1 | 1 | 0% | 2,912 | 4,006 | +38% | 0 | 0 | — |
case-16 | fail→pass | 14,807 | 12,867 | -13% | 1 | 1 | 0% | 2,771 | 5,174 | +87% | 0 | 0 | — |
case-21 | pass→pass | 7,224 | 6,578 | -9% | 1 | 1 | 0% | 1,573 | 3,627 | +131% | 0 | 0 | — |
case-01 | fail→pass | 18,968 | 17,263 | -9% | 1 | 1 | 0% | 4,177 | 5,604 | +34% | 0 | 0 | — |
case-02 | fail→pass | 19,527 | 9,230 | -53% | 1 | 1 | 0% | 3,722 | 4,203 | +13% | 0 | 0 | — |
case-03 | pass→pass | 13,372 | 10,840 | -19% | 1 | 1 | 0% | 2,311 | 4,414 | +91% | 0 | 0 | — |
case-04 | fail→fail | 13,110 | 9,084 | -31% | 1 | 1 | 0% | 2,576 | 3,477 | +35% | 0 | 0 | — |
case-05 | pass→pass | 12,605 | 7,826 | -38% | 1 | 1 | 0% | 2,100 | 3,704 | +76% | 0 | 0 | — |
case-10 | fail→pass | 11,558 | 10,120 | -12% | 1 | 1 | 0% | 2,074 | 4,222 | +104% | 0 | 0 | — |
case-06 | pass→pass | 15,408 | 3,214 | -79% | 1 | 1 | 0% | 2,072 | 2,956 | +43% | 0 | 0 | — |
case-07 | fail→pass | 5,670 | 3,612 | -36% | 1 | 1 | 0% | 913 | 2,943 | +222% | 0 | 0 | — |
case-08 | pass→pass | 6,872 | 3,761 | -45% | 1 | 1 | 0% | 1,126 | 2,923 | +160% | 0 | 0 | — |
case-09 | pass→pass | 8,423 | 3,967 | -53% | 1 | 1 | 0% | 1,332 | 3,048 | +129% | 0 | 0 | — |
case-11 | pass→pass | 12,519 | 7,857 | -37% | 1 | 1 | 0% | 2,341 | 3,754 | +60% | 0 | 0 | — |
case-12 | pass→fail | 9,234 | 6,998 | -24% | 1 | 1 | 0% | 1,682 | 3,610 | +115% | 0 | 0 | — |
case-13 | pass→pass | 13,571 | 11,706 | -14% | 1 | 1 | 0% | 2,370 | 4,770 | +101% | 0 | 0 | — |
case-14 | fail→pass | 12,119 | 10,279 | -15% | 1 | 1 | 0% | 2,290 | 4,407 | +92% | 0 | 0 | — |
case-17 | pass→pass | 3,008 | 2,352 | -22% | 1 | 1 | 0% | 452 | 2,808 | +521% | 0 | 0 | — |
case-18 | pass→pass | 5,018 | 3,366 | -33% | 1 | 1 | 0% | 807 | 2,909 | +260% | 0 | 0 | — |
case-19 | fail→pass | 8,134 | 4,609 | -43% | 1 | 1 | 0% | 1,433 | 3,063 | +114% | 0 | 0 | — |
case-20 | pass→pass | 12,769 | 7,857 | -38% | 1 | 1 | 0% | 2,249 | 3,874 | +72% | 0 | 0 | — |
case-22 | pass→pass | 9,498 | 12,366 | +30% | 1 | 1 | 0% | 1,871 | 4,057 | +117% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +32 percentage points is the difference between those two pass rates over the 22 comparable cases. 1 case got worse with the skill loaded, and it is included in that figure.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.