关于 qdrant-vector-database-integration
面向 Java 应用集成 Qdrant 向量搜索的技能指南,提供 Spring Boot 和 LangChain4j 模式,涵盖集合管理、向量操作、过滤搜索与 RAG。
主要功能
- 01Java 客户端配置
- 02集合管理
- 03向量写入与相似度搜索
- 04Spring Boot 集成
- 05LangChain4j 嵌入存储
- 06过滤与多租户搜索
适用场景
- 01为 Spring Boot 添加语义搜索
- 02构建 Java RAG 流水线
- 03创建带过滤条件的向量搜索
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ giuseppe-trisciuoglio/ developer-kit --skill qdrant-vector-database-integration安装后在 Claude Code 中输入/qdrant-vector-database-integration确认已加载。
附带文件references/examples.mdreferences/references.md
详细介绍
Qdrant 向量数据库集成
概述
Qdrant 是一款面向 AI 的向量数据库,适用于语义搜索和相似度检索。本技能提供了将 Qdrant 集成到 Java 应用程序中的模式,重点介绍 Spring Boot 集成和 LangChain4j 框架支持。为 RAG 系统、推荐引擎和语义搜索应用启用高效的向量搜索能力。
适用场景
在以下情况下使用本技能:
- 在 Spring Boot 应用程序中实现语义搜索或推荐系统
- 使用 Java 和 LangChain4j 构建检索增强生成(RAG)管道
- 为 AI 和机器学习应用集成向量数据库
- 使用筛选查询进行高性能相似度搜索
- 为具备上下文感知能力的应用存储和检索嵌入
入门:配置 Qdrant
开始集成前,请先部署 Qdrant 实例。
使用 Docker 进行本地开发
# 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
通过以下方式访问 Qdrant:
- REST API:
http://localhost:6333 - gRPC API:
http://localhost:6334(Java 客户端使用)
Java 客户端核心集成
将依赖项添加到构建配置中,并初始化客户端以进行程序化访问。
依赖项配置
Maven:
<dependency>
<groupId>io.qdrant</groupId>
<artifactId>client</artifactId>
<version>1.15.0</version>
</dependency>
Gradle:
implementation 'io.qdrant:client:1.15.0'
客户端初始化
创建并配置 Qdrant 客户端,供应用程序使用:
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(
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());
集合管理
使用适当的距离度量和维度创建并配置向量集合。
创建集合
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();
向量操作
执行常见的向量操作,包括写入、搜索和筛选。
写入点
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")
))
.build()
);
client.upsertAsync("search-collection", points).get();
向量搜索
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;
// Basic similarity search
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(
SearchPoints.newBuilder()
.setCollectionName("search-collection")
.addAllVector(List.of(0.6235f, 0.123f, 0.532f, 0.123f))
.setFilter(Filter.newBuilder()
.addMust(range("rand_number",
Range.newBuilder().setGte(3).build()))
.build())
.setLimit(5)
.build()).get();
Spring Boot 集成
使用依赖注入和适当的配置将 Qdrant 集成到 Spring Boot 中。
配置类
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);
}
}
服务层实现
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);
}
}
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);
}
}
}
LangChain4j 集成
利用 LangChain4j 实现高级向量存储抽象和 RAG。
依赖项配置
Maven:
<dependency>
<groupId>dev.langchain4j</groupId>
<artifactId>langchain4j-qdrant</artifactId>
<version>1.7.0</version>
</dependency>
QdrantEmbeddingStore 配置
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();
}
@Bean
public EmbeddingModel embeddingModel() {
return new AllMiniLmL6V2EmbeddingModel();
}
@Bean
public EmbeddingStoreIngestor embeddingStoreIngestor(
EmbeddingStore<TextSegment> embeddingStore,
EmbeddingModel embeddingModel) {
return EmbeddingStoreIngestor.builder()
.embeddingStore(embeddingStore)
.embeddingModel(embeddingModel)
.build();
}
}
RAG 服务实现
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();
}
}
示例
基本搜索实现
// 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);
}
}
最佳实践
向量数据库配置
- 使用适当的距离度量:文本使用 Cosine,数值数据使用 Euclidean
- 根据嵌入模型规范优化向量维度
- 配置合理的集合命名约定
- 监控性能并优化搜索参数
Spring Boot 集成
- 始终使用构造函数注入进行依赖注入
- 通过适当的异常处理来处理异步操作
- 配置连接超时和重试策略
- 为生产环境使用适当的 Bean 配置
安全注意事项
- 切勿在代码中硬编码 API 密钥
- 使用环境变量或 Spring 配置属性
- 实施适当的身份验证和授权
- 在生产连接中使用 TLS
性能优化
- 批量执行操作以批量写入
- 使用适当的限制和筛选条件
- 监控内存使用情况和连接池
- 对大型数据集考虑分片
高级模式
多租户向量存储
// Implement collection-based multi-tenancy
public class MultiTenantVectorService {
private final QdrantClient client;
public void upsertForTenant(String tenantId, List<PointStruct> points) {
String collectionName = "tenant_" + tenantId + "_documents";
client.upsertAsync(collectionName, points).get();
}
}
带筛选条件的混合搜索
// 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();
return client.searchAsync(
SearchPoints.newBuilder()
.setCollectionName(collectionName)
.addAllVector(queryVector)
.setFilter(filter)
.build()
).get();
}
参考资料
如需全面的技术细节和高级模式,请参阅:
- Qdrant API 参考 - 完整的客户端 API 文档
- 完整的 Spring Boot 示例 - 完整的应用程序实现
- Qdrant 官方文档 - 核心文档
- LangChain4j 文档 - 框架专属模式
评论
支持 Markdown