qdrant · diff

git:20260228.3187e79 to git:20260324.a02e282

88 added, 394 removed. Audit A to A.

---
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 integration and LangChain4j framework support. Enable efficient vector search capabilities for RAG systems, recommendation engines, and semantic search applications.
+ 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
- Use this skill when implementing:
- Semantic search or recommendation systems in Spring Boot applications
- - Retrieval-Augmented Generation (RAG) pipelines with Java and LangChain4j
- - Vector database integration for AI and machine learning applications
+ - RAG pipelines with Java and LangChain4j
+ - Vector database integration for AI/ML applications
- High-performance similarity search with filtered queries
- - Embedding storage and retrieval for context-aware applications
## Instructions
- Follow these steps to integrate Qdrant with your Java application:
-
- ### 1. Deploy Qdrant Instance
-
- Start Qdrant using Docker for local development:
-
- ```bash
- docker run -p 6333:6333 -p 6334:6334 \
- -v "$(pwd)/qdrant_storage:/qdrant/storage:z" \
- qdrant/qdrant
- ```
-
- ### 2. Add Dependencies
-
- Include Qdrant client dependencies in your build configuration:
-
- ```xml
- <dependency>
- <groupId>io.qdrant</groupId>
- <artifactId>client</artifactId>
- <version>1.15.0</version>
- </dependency>
- ```
-
- ### 3. Initialize Qdrant Client
-
- Create and configure the Qdrant client:
-
- ```java
- QdrantClient client = new QdrantClient(
- QdrantGrpcClient.newBuilder("localhost").build()
- );
- ```
-
- ### 4. Create Collection
-
- Set up a vector collection with appropriate dimensions:
-
- ```java
- client.createCollectionAsync("search-collection",
- VectorParams.newBuilder()
- .setDistance(Distance.Cosine)
- .setSize(384)
- .build()
- ).get();
- ```
-
- ### 5. Perform Vector Operations
-
- Upsert and search vectors:
-
- ```java
- // Upsert vectors
- List<PointStruct> points = List.of(
- PointStruct.newBuilder()
- .setId(id(1))
- .setVectors(vectors(0.05f, 0.61f, 0.76f, 0.74f))
- .build()
- );
- client.upsertAsync("search-collection", points).get();
-
- // Search vectors
- List<ScoredPoint> results = client.queryAsync(
- QueryPoints.newBuilder()
- .setCollectionName("search-collection")
- .setLimit(5)
- .setQuery(nearest(0.2f, 0.1f, 0.9f, 0.7f))
- .build()
- ).get();
- ```
-
- ### 6. Integrate with LangChain4j
-
- Use LangChain4j's QdrantEmbeddingStore for RAG applications:
-
- ```java
- EmbeddingStore<TextSegment> embeddingStore = QdrantEmbeddingStore.builder()
- .collectionName("rag-collection")
- .host("localhost")
- .port(6334)
- .build();
- ```
-
- ## Getting Started: Qdrant Setup
-
- To begin integration, first deploy a Qdrant instance.
-
- ### Local Development with Docker
+ ### 1. Deploy Qdrant with Docker
```bash
- # Pull the latest Qdrant image
- docker pull qdrant/qdrant
-
- # Run the Qdrant container
docker run -p 6333:6333 -p 6334:6334 \
-v "$(pwd)/qdrant_storage:/qdrant/storage:z" \
qdrant/qdrant
```
- Access Qdrant via:
- - **REST API**: `http://localhost:6333`
- - **gRPC API**: `http://localhost:6334` (used by Java client)
-
- ## Core Java Client Integration
-
- Add dependencies to your build configuration and initialize the client for programmatic access.
+ Access: REST API at `http://localhost:6333`, gRPC at `http://localhost:6334`.
- ### Dependency Configuration
+ ### 2. Add Dependencies
**Maven:**
```xml
<dependency>
<groupId>io.qdrant</groupId>
<artifactId>client</artifactId>
<version>1.15.0</version>
</dependency>
```
**Gradle:**
```gradle
implementation 'io.qdrant:client:1.15.0'
```
- ### Client Initialization
-
- Create and configure the Qdrant client for application use:
+ ### 3. Initialize Client
```java
- import io.qdrant.client.QdrantClient;
- import io.qdrant.client.QdrantGrpcClient;
-
- // Basic local connection
QdrantClient client = new QdrantClient(
QdrantGrpcClient.newBuilder("localhost").build());
+ ```
- // Secure connection with API key
- QdrantClient secureClient = new QdrantClient(
+ For production with API key:
+ ```java
+ QdrantClient client = new QdrantClient(
QdrantGrpcClient.newBuilder("localhost", 6334, false)
.withApiKey("YOUR_API_KEY")
.build());
-
- // Managed connection with TLS
- QdrantClient tlsClient = new QdrantClient(
- QdrantGrpcClient.newBuilder(channel)
- .withApiKey("YOUR_API_KEY")
- .build());
```
- ## Collection Management
-
- Create and configure vector collections with appropriate distance metrics and dimensions.
-
- ### Create Collections
+ ### 4. Create Collection
```java
- import io.qdrant.client.grpc.Collections.Distance;
- import io.qdrant.client.grpc.Collections.VectorParams;
- import java.util.concurrent.ExecutionException;
-
- // Create a collection with cosine distance
client.createCollectionAsync("search-collection",
VectorParams.newBuilder()
.setDistance(Distance.Cosine)
.setSize(384)
- .build()).get();
-
- // Create collection with configuration
- client.createCollectionAsync("recommendation-engine",
- VectorParams.newBuilder()
- .setDistance(Distance.Euclidean)
- .setSize(512)
- .build()).get();
+ .build()
+ ).get();
```
- ## Vector Operations
-
- Perform common vector operations including upsert, search, and filtering.
+ **Validation:** Verify the collection was created by checking `client.getCollectionAsync("search-collection").get()`.
- ### Upsert Points
+ ### 5. Upsert Vectors
```java
- import io.qdrant.client.grpc.Points.PointStruct;
- import java.util.List;
- import java.util.Map;
- import static io.qdrant.client.PointIdFactory.id;
- import static io.qdrant.client.ValueFactory.value;
- import static io.qdrant.client.VectorsFactory.vectors;
-
- // Batch upsert vector points
List<PointStruct> 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"),
- "content", value("Spring Boot framework documentation")
- ))
- .build(),
- PointStruct.newBuilder()
- .setId(id(2))
- .setVectors(vectors(0.19f, 0.81f, 0.75f, 0.11f))
- .putAllPayload(Map.of(
- "title", value("Qdrant Vector Database"),
- "content", value("Vector database for AI applications")
- ))
+ .putAllPayload(Map.of("title", value("Spring Boot Documentation")))
.build()
);
-
client.upsertAsync("search-collection", points).get();
```
- ### Vector Search
+ **Validation:** Check that `client.upsertAsync(...).get()` completes without throwing.
- ```java
- import io.qdrant.client.grpc.Points.QueryPoints;
- import io.qdrant.client.grpc.Points.ScoredPoint;
- import static io.qdrant.client.QueryFactory.nearest;
- import java.util.List;
+ ### 6. Search Vectors
- // Basic similarity search
+ ```java
List<ScoredPoint> results = client.queryAsync(
QueryPoints.newBuilder()
.setCollectionName("search-collection")
.setLimit(5)
.setQuery(nearest(0.2f, 0.1f, 0.9f, 0.7f))
.build()
).get();
+ ```
- // Search with filters
- List<ScoredPoint> filteredResults = client.searchAsync(
+ Filtered search:
+ ```java
+ List<ScoredPoint> results = client.searchAsync(
SearchPoints.newBuilder()
.setCollectionName("search-collection")
- .addAllVector(List.of(0.6235f, 0.123f, 0.532f, 0.123f))
+ .addAllVector(List.of(0.62f, 0.12f, 0.53f, 0.12f))
.setFilter(Filter.newBuilder()
- .addMust(range("rand_number",
- Range.newBuilder().setGte(3).build()))
+ .addMust(range("category", Range.newBuilder().setEq("docs").build()))
.build())
.setLimit(5)
.build()).get();
```
- ## Spring Boot Integration
-
- Integrate Qdrant with Spring Boot using dependency injection and proper configuration.
+ ## LangChain4j Integration
- ### Configuration Class
+ For RAG pipelines, use LangChain4j's high-level abstractions:
```java
- import io.qdrant.client.QdrantClient;
- import io.qdrant.client.QdrantGrpcClient;
- import org.springframework.beans.factory.annotation.Value;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
-
- @Configuration
- public class QdrantConfig {
-
- @Value("${qdrant.host:localhost}")
- private String host;
-
- @Value("${qdrant.port:6334}")
- private int port;
-
- @Value("${qdrant.api-key:}")
- private String apiKey;
-
- @Bean
- public QdrantClient qdrantClient() {
- QdrantGrpcClient grpcClient = QdrantGrpcClient.newBuilder(host, port, false)
- .withApiKey(apiKey)
- .build();
-
- return new QdrantClient(grpcClient);
- }
- }
+ EmbeddingStore<TextSegment> embeddingStore = QdrantEmbeddingStore.builder()
+ .collectionName("rag-collection")
+ .host("localhost")
+ .port(6334)
+ .apiKey("YOUR_API_KEY")
+ .build();
```
- ### Service Layer Implementation
-
+ Spring Boot configuration with LangChain4j:
```java
- import org.springframework.stereotype.Service;
- import java.util.List;
- import java.util.concurrent.ExecutionException;
-
- @Service
- public class VectorSearchService {
-
- private final QdrantClient qdrantClient;
-
- public VectorSearchService(QdrantClient qdrantClient) {
- this.qdrantClient = qdrantClient;
- }
-
- public List<ScoredPoint> search(String collectionName, List<Float> queryVector) {
- try {
- return qdrantClient.queryAsync(
- QueryPoints.newBuilder()
- .setCollectionName(collectionName)
- .setLimit(5)
- .setQuery(nearest(queryVector))
- .build()
- ).get();
- } catch (InterruptedException | ExecutionException e) {
- throw new RuntimeException("Qdrant search failed", e);
- }
- }
+ @Bean
+ public EmbeddingStore<TextSegment> embeddingStore() {
+ return QdrantEmbeddingStore.builder()
+ .collectionName("rag-collection")
+ .host(host)
+ .port(port)
+ .build();
+ }
- public void upsertPoints(String collectionName, List<PointStruct> points) {
- try {
- qdrantClient.upsertAsync(collectionName, points).get();
- } catch (InterruptedException | ExecutionException e) {
- throw new RuntimeException("Qdrant upsert failed", e);
- }
- }
+ @Bean
+ public EmbeddingModel embeddingModel() {
+ return new AllMiniLmL6V2EmbeddingModel();
}
```
- ## LangChain4j Integration
-
- Leverage LangChain4j for high-level vector store abstractions and RAG implementations.
-
- ### Dependency Setup
-
- **Maven:**
- ```xml
- <dependency>
- <groupId>dev.langchain4j</groupId>
- <artifactId>langchain4j-qdrant</artifactId>
- <version>1.7.0</version>
- </dependency>
- ```
+ ## Spring Boot Integration
- ### QdrantEmbeddingStore Configuration
+ Inject the client via configuration:
```java
- import dev.langchain4j.data.segment.TextSegment;
- import dev.langchain4j.embedding.EmbeddingModel;
- import dev.langchain4j.embedding.allminilml6v2.AllMiniLmL6V2EmbeddingModel;
- import dev.langchain4j.store.embedding.EmbeddingStore;
- import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
- import dev.langchain4j.store.embedding.qdrant.QdrantEmbeddingStore;
- import org.springframework.context.annotation.Bean;
- import org.springframework.context.annotation.Configuration;
-
@Configuration
- public class Langchain4jConfig {
-
- @Bean
- public EmbeddingStore<TextSegment> embeddingStore() {
- return QdrantEmbeddingStore.builder()
- .collectionName("rag-collection")
- .host("localhost")
- .port(6334)
- .apiKey("YOUR_API_KEY")
- .build();
- }
+ public class QdrantConfig {
+ @Value("${qdrant.host:localhost}")
+ private String host;
- @Bean
- public EmbeddingModel embeddingModel() {
- return new AllMiniLmL6V2EmbeddingModel();
- }
+ @Value("${qdrant.port:6334}")
+ private int port;
@Bean
- public EmbeddingStoreIngestor embeddingStoreIngestor(
- EmbeddingStore<TextSegment> embeddingStore,
- EmbeddingModel embeddingModel) {
- return EmbeddingStoreIngestor.builder()
- .embeddingStore(embeddingStore)
- .embeddingModel(embeddingModel)
- .build();
- }
- }
- ```
-
- ### RAG Service Implementation
-
- ```java
- import dev.langchain4j.data.segment.TextSegment;
- import dev.langchain4j.embedding.EmbeddingModel;
- import dev.langchain4j.store.embedding.EmbeddingStore;
- import dev.langchain4j.store.embedding.EmbeddingStoreIngestor;
- import org.springframework.stereotype.Service;
- import java.util.List;
-
- @Service
- public class RagService {
-
- private final EmbeddingStoreIngestor ingestor;
-
- public RagService(EmbeddingStoreIngestor ingestor) {
- this.ingestor = ingestor;
- }
-
- public void ingestDocument(String text) {
- TextSegment segment = TextSegment.from(text);
- ingestor.ingest(segment);
- }
-
- public List<TextSegment> findRelevant(String query) {
- EmbeddingStore<TextSegment> embeddingStore = ingestor.getEmbeddingStore();
- return embeddingStore.findRelevant(
- ingestor.getEmbeddingModel().embed(query).content(),
- 5,
- 0.7
- ).stream()
- .map(match -> match.embedded())
- .toList();
+ public QdrantClient qdrantClient() {
+ return new QdrantClient(
+ QdrantGrpcClient.newBuilder(host, port, false).build());
}
}
```
## Examples
- ### Basic Search Implementation
+ ### REST Search Endpoint
```java
- // Create simple search endpoint
@RestController
@RequestMapping("/api/search")
public class SearchController {
-
private final VectorSearchService searchService;
public SearchController(VectorSearchService searchService) {
this.searchService = searchService;
}
@GetMapping
public List<ScoredPoint> search(@RequestParam String query) {
- // Convert query to embedding (requires embedding model)
List<Float> queryVector = embeddingModel.embed(query).content().vectorAsList();
return searchService.search("documents", queryVector);
}
}
```
## Best Practices
- ### Vector Database Configuration
- - Use appropriate distance metrics: Cosine for text, Euclidean for numerical data
- - Optimize vector dimensions based on embedding model specifications
- - Configure proper collection naming conventions
- - Monitor performance and optimize search parameters
-
- ### Spring Boot Integration
- - Always use constructor injection for dependency injection
- - Handle async operations with proper exception handling
- - Configure connection timeouts and retry policies
- - Use proper bean configuration for production environments
-
- ### Security Considerations
- - Never hardcode API keys in code
- - Use environment variables or Spring configuration properties
- - Implement proper authentication and authorization
- - Use TLS for production connections
-
- ### Performance Optimization
- - Batch operations for bulk upserts
- - Use appropriate limits and filters
- - Monitor memory usage and connection pooling
- - Consider sharding for large datasets
+ - **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 Vector Storage
- ```java
- // Implement collection-based multi-tenancy
- public class MultiTenantVectorService {
- private final QdrantClient client;
+ ### Multi-tenant Storage
- public void upsertForTenant(String tenantId, List<PointStruct> points) {
- String collectionName = "tenant_" + tenantId + "_documents";
- client.upsertAsync(collectionName, points).get();
- }
+ ```java
+ public void upsertForTenant(String tenantId, List<PointStruct> points) {
+ String collectionName = "tenant_" + tenantId + "_documents";
+ client.upsertAsync(collectionName, points).get();
}
```
- ### Hybrid Search with Filters
- ```java
- // Combine vector similarity with metadata filtering
- public List<ScoredPoint> hybridSearch(String collectionName, List<Float> queryVector,
- String category, Date dateRange) {
- Filter filter = Filter.newBuilder()
- .addMust(range("created_at",
- Range.newBuilder().setGte(dateRange.getTime()).build()))
- .addMust(exactMatch("category", category))
- .build();
+ ### Docker Compose for Production
- return client.searchAsync(
- SearchPoints.newBuilder()
- .setCollectionName(collectionName)
- .addAllVector(queryVector)
- .setFilter(filter)
- .build()
- ).get();
- }
+ ```yaml
+ services:
+ qdrant:
+ image: qdrant/qdrant:v1.7.0
+ ports:
+ - "6333:6333"
+ - "6334:6334"
+ volumes:
+ - qdrant_storage:/qdrant/storage
```
## References
- For comprehensive technical details and advanced patterns, see:
- - [Qdrant API Reference](references/references.md) - Complete client API documentation
- - [Complete Spring Boot Examples](references/examples.md) - Full application implementations
- - [Official Qdrant Documentation](https://qdrant.tech/documentation/) - Core documentation
- - [LangChain4j Documentation](https://langchain4j.dev/) - Framework-specific patterns
+ - [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; mismatched dimensions will cause errors.
- - **Input Validation**: Always validate and sanitize document content before ingestion into the vector store; untrusted user-provided or third-party documents may contain prompt injection payloads that could influence RAG-based model responses.
- - **Content Filtering**: Apply content filtering on documents retrieved from the embedding store before passing them to the LLM to mitigate indirect prompt injection risks.
- - Large vector collections require proper indexing configuration for acceptable search performance.
- - Cosine distance is recommended for normalized embeddings; Euclidean for non-normalized.
- - Qdrant gRPC API (port 6334) should be used for production; REST API (port 6333) for debugging.
- - Implement proper connection pooling to avoid connection exhaustion under load.
- - Batch upsert operations are more efficient than individual point insertions.
- - Be aware of payload size limits when storing metadata with vectors.
- - Collection recreation deletes all data; implement backup strategies for production.
- - Filtering on large datasets without proper indexing can cause performance degradation.
+ - 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.
+