--- name: qdrant description: Provides Qdrant vector database integration patterns with LangChain4j. Handles embedding storage, similarity search, and vector management for Java applications. Use when implementing vector-based retrieval for RAG systems, semantic search, or recommendation engines. allowed-tools: Read, Write, Edit, Bash, Glob, Grep --- # Qdrant Vector Database Integration ## Overview Qdrant is an AI-native vector database for semantic search and similarity retrieval. This skill provides patterns for integrating Qdrant with Java applications, focusing on Spring Boot and LangChain4j integration. ## When to Use - Semantic search or recommendation systems in Spring Boot applications - RAG pipelines with Java and LangChain4j - Vector database integration for AI/ML applications - High-performance similarity search with filtered queries ## Instructions ### 1. Deploy Qdrant with Docker ```bash docker run -p 6333:6333 -p 6334:6334 \ -v "$(pwd)/qdrant_storage:/qdrant/storage:z" \ qdrant/qdrant ``` Access: REST API at `http://localhost:6333`, gRPC at `http://localhost:6334`. ### 2. Add Dependencies **Maven:** ```xml io.qdrant client 1.15.0 ``` **Gradle:** ```gradle implementation 'io.qdrant:client:1.15.0' ``` ### 3. Initialize Client ```java QdrantClient client = new QdrantClient( QdrantGrpcClient.newBuilder("localhost").build()); ``` For production with API key: ```java QdrantClient client = new QdrantClient( QdrantGrpcClient.newBuilder("localhost", 6334, false) .withApiKey("YOUR_API_KEY") .build()); ``` ### 4. Create Collection ```java client.createCollectionAsync("search-collection", VectorParams.newBuilder() .setDistance(Distance.Cosine) .setSize(384) .build() ).get(); ``` **Validation:** Verify the collection was created by checking `client.getCollectionAsync("search-collection").get()`. ### 5. Upsert Vectors ```java List points = List.of( PointStruct.newBuilder() .setId(id(1)) .setVectors(vectors(0.05f, 0.61f, 0.76f, 0.74f)) .putAllPayload(Map.of("title", value("Spring Boot Documentation"))) .build() ); client.upsertAsync("search-collection", points).get(); ``` **Validation:** Check that `client.upsertAsync(...).get()` completes without throwing. ### 6. Search Vectors ```java List results = client.queryAsync( QueryPoints.newBuilder() .setCollectionName("search-collection") .setLimit(5) .setQuery(nearest(0.2f, 0.1f, 0.9f, 0.7f)) .build() ).get(); ``` Filtered search: ```java List results = client.searchAsync( SearchPoints.newBuilder() .setCollectionName("search-collection") .addAllVector(List.of(0.62f, 0.12f, 0.53f, 0.12f)) .setFilter(Filter.newBuilder() .addMust(range("category", Range.newBuilder().setEq("docs").build())) .build()) .setLimit(5) .build()).get(); ``` ## LangChain4j Integration For RAG pipelines, use LangChain4j's high-level abstractions: ```java EmbeddingStore embeddingStore = QdrantEmbeddingStore.builder() .collectionName("rag-collection") .host("localhost") .port(6334) .apiKey("YOUR_API_KEY") .build(); ``` Spring Boot configuration with LangChain4j: ```java @Bean public EmbeddingStore embeddingStore() { return QdrantEmbeddingStore.builder() .collectionName("rag-collection") .host(host) .port(port) .build(); } @Bean public EmbeddingModel embeddingModel() { return new AllMiniLmL6V2EmbeddingModel(); } ``` ## Spring Boot Integration Inject the client via configuration: ```java @Configuration public class QdrantConfig { @Value("${qdrant.host:localhost}") private String host; @Value("${qdrant.port:6334}") private int port; @Bean public QdrantClient qdrantClient() { return new QdrantClient( QdrantGrpcClient.newBuilder(host, port, false).build()); } } ``` ## Examples ### REST Search Endpoint ```java @RestController @RequestMapping("/api/search") public class SearchController { private final VectorSearchService searchService; public SearchController(VectorSearchService searchService) { this.searchService = searchService; } @GetMapping public List search(@RequestParam String query) { List queryVector = embeddingModel.embed(query).content().vectorAsList(); return searchService.search("documents", queryVector); } } ``` ## Best Practices - **Distance metric**: Cosine for normalized text embeddings, Euclidean for non-normalized. - **Batch upserts**: Use batch operations over individual point insertions. - **Connection pooling**: Configure connection pooling for high-throughput production workloads. - **Error handling**: Wrap async operations in try/catch for ExecutionException/InterruptedException. - **API keys**: Store in environment variables or Spring config, never hardcode. ## Advanced Patterns ### Multi-tenant Storage ```java public void upsertForTenant(String tenantId, List points) { String collectionName = "tenant_" + tenantId + "_documents"; client.upsertAsync(collectionName, points).get(); } ``` ### Docker Compose for Production ```yaml services: qdrant: image: qdrant/qdrant:v1.7.0 ports: - "6333:6333" - "6334:6334" volumes: - qdrant_storage:/qdrant/storage ``` ## References - [Qdrant API Reference](references/references.md) — Complete client API documentation - [Complete Spring Boot Examples](references/examples.md) — Full application implementations - [Qdrant Documentation](https://qdrant.tech/documentation/) - [LangChain4j Documentation](https://langchain4j.dev/) ## Constraints and Warnings - Vector dimensions must match the embedding model exactly; mismatched dimensions cause upsert errors. - **Input validation**: Sanitize all document content before ingestion; untrusted payloads may contain prompt injection attacks. - **Content filtering**: Apply content filtering on retrieved documents before passing them to the LLM. - Large collections require proper indexing for acceptable search performance. - Use gRPC API (port 6334) for production; REST API (port 6333) for debugging only. - Collection recreation deletes all data; implement backup strategies for production environments.