如何在本地开始使用 Qdrant
在这个简短的示例中,您将使用 Python 客户端创建一个集合,将数据加载到其中并运行基本的搜索查询。
下载并运行
首先,从 Dockerhub 下载最新的 Qdrant 镜像
docker pull qdrant/qdrant
然后,运行服务
docker run -p 6333:6333 -p 6334:6334 \
-v "$(pwd)/qdrant_storage:/qdrant/storage:z" \
qdrant/qdrant
在默认配置下,所有数据将存储在 ./qdrant_storage
目录中。这也是容器和宿主机都能看到的唯一目录。
Qdrant 现在可访问
- REST API: localhost:6333
- Web UI: localhost:6333/dashboard
- GRPC API: localhost:6334
初始化客户端
from qdrant_client import QdrantClient
client = QdrantClient(url="http://localhost:6333")
import { QdrantClient } from "@qdrant/js-client-rest";
const client = new QdrantClient({ host: "localhost", port: 6333 });
use qdrant_client::Qdrant;
// The Rust client uses Qdrant's gRPC interface
let client = Qdrant::from_url("http://localhost:6334").build()?;
import io.qdrant.client.QdrantClient;
import io.qdrant.client.QdrantGrpcClient;
// The Java client uses Qdrant's gRPC interface
QdrantClient client = new QdrantClient(
QdrantGrpcClient.newBuilder("localhost", 6334, false).build());
using Qdrant.Client;
// The C# client uses Qdrant's gRPC interface
var client = new QdrantClient("localhost", 6334);
import "github.com/qdrant/go-client/qdrant"
// The Go client uses Qdrant's gRPC interface
client, err := qdrant.NewClient(&qdrant.Config{
Host: "localhost",
Port: 6334,
})
创建集合
您将把所有向量数据存储在一个 Qdrant 集合中。我们将其命名为 test_collection
。这个集合将使用点积距离度量来比较向量。
from qdrant_client.models import Distance, VectorParams
client.create_collection(
collection_name="test_collection",
vectors_config=VectorParams(size=4, distance=Distance.DOT),
)
await client.createCollection("test_collection", {
vectors: { size: 4, distance: "Dot" },
});
use qdrant_client::qdrant::{CreateCollectionBuilder, VectorParamsBuilder};
client
.create_collection(
CreateCollectionBuilder::new("test_collection")
.vectors_config(VectorParamsBuilder::new(4, Distance::Dot)),
)
.await?;
import io.qdrant.client.grpc.Collections.Distance;
import io.qdrant.client.grpc.Collections.VectorParams;
client.createCollectionAsync("test_collection",
VectorParams.newBuilder().setDistance(Distance.Dot).setSize(4).build()).get();
using Qdrant.Client.Grpc;
await client.CreateCollectionAsync(collectionName: "test_collection", vectorsConfig: new VectorParams
{
Size = 4, Distance = Distance.Dot
});
import (
"context"
"github.com/qdrant/go-client/qdrant"
)
client.CreateCollection(context.Background(), &qdrant.CreateCollection{
CollectionName: "{collection_name}",
VectorsConfig: qdrant.NewVectorsConfig(&qdrant.VectorParams{
Size: 4,
Distance: qdrant.Distance_Cosine,
}),
})
添加向量
现在让我们添加一些带有载荷的向量。载荷是您希望与向量关联的其他数据。
from qdrant_client.models import PointStruct
operation_info = client.upsert(
collection_name="test_collection",
wait=True,
points=[
PointStruct(id=1, vector=[0.05, 0.61, 0.76, 0.74], payload={"city": "Berlin"}),
PointStruct(id=2, vector=[0.19, 0.81, 0.75, 0.11], payload={"city": "London"}),
PointStruct(id=3, vector=[0.36, 0.55, 0.47, 0.94], payload={"city": "Moscow"}),
PointStruct(id=4, vector=[0.18, 0.01, 0.85, 0.80], payload={"city": "New York"}),
PointStruct(id=5, vector=[0.24, 0.18, 0.22, 0.44], payload={"city": "Beijing"}),
PointStruct(id=6, vector=[0.35, 0.08, 0.11, 0.44], payload={"city": "Mumbai"}),
],
)
print(operation_info)
const operationInfo = await client.upsert("test_collection", {
wait: true,
points: [
{ id: 1, vector: [0.05, 0.61, 0.76, 0.74], payload: { city: "Berlin" } },
{ id: 2, vector: [0.19, 0.81, 0.75, 0.11], payload: { city: "London" } },
{ id: 3, vector: [0.36, 0.55, 0.47, 0.94], payload: { city: "Moscow" } },
{ id: 4, vector: [0.18, 0.01, 0.85, 0.80], payload: { city: "New York" } },
{ id: 5, vector: [0.24, 0.18, 0.22, 0.44], payload: { city: "Beijing" } },
{ id: 6, vector: [0.35, 0.08, 0.11, 0.44], payload: { city: "Mumbai" } },
],
});
console.debug(operationInfo);
use qdrant_client::qdrant::{PointStruct, UpsertPointsBuilder};
let points = vec![
PointStruct::new(1, vec![0.05, 0.61, 0.76, 0.74], [("city", "Berlin".into())]),
PointStruct::new(2, vec![0.19, 0.81, 0.75, 0.11], [("city", "London".into())]),
PointStruct::new(3, vec![0.36, 0.55, 0.47, 0.94], [("city", "Moscow".into())]),
// ..truncated
];
let response = client
.upsert_points(UpsertPointsBuilder::new("test_collection", points).wait(true))
.await?;
dbg!(response);
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;
import io.qdrant.client.grpc.Points.PointStruct;
import io.qdrant.client.grpc.Points.UpdateResult;
UpdateResult operationInfo =
client
.upsertAsync(
"test_collection",
List.of(
PointStruct.newBuilder()
.setId(id(1))
.setVectors(vectors(0.05f, 0.61f, 0.76f, 0.74f))
.putAllPayload(Map.of("city", value("Berlin")))
.build(),
PointStruct.newBuilder()
.setId(id(2))
.setVectors(vectors(0.19f, 0.81f, 0.75f, 0.11f))
.putAllPayload(Map.of("city", value("London")))
.build(),
PointStruct.newBuilder()
.setId(id(3))
.setVectors(vectors(0.36f, 0.55f, 0.47f, 0.94f))
.putAllPayload(Map.of("city", value("Moscow")))
.build()))
// Truncated
.get();
System.out.println(operationInfo);
using Qdrant.Client.Grpc;
var operationInfo = await client.UpsertAsync(collectionName: "test_collection", points: new List<PointStruct>
{
new()
{
Id = 1,
Vectors = new float[]
{
0.05f, 0.61f, 0.76f, 0.74f
},
Payload = {
["city"] = "Berlin"
}
},
new()
{
Id = 2,
Vectors = new float[]
{
0.19f, 0.81f, 0.75f, 0.11f
},
Payload = {
["city"] = "London"
}
},
new()
{
Id = 3,
Vectors = new float[]
{
0.36f, 0.55f, 0.47f, 0.94f
},
Payload = {
["city"] = "Moscow"
}
},
// Truncated
});
Console.WriteLine(operationInfo);
import (
"context"
"fmt"
"github.com/qdrant/go-client/qdrant"
)
operationInfo, err := client.Upsert(context.Background(), &qdrant.UpsertPoints{
CollectionName: "test_collection",
Points: []*qdrant.PointStruct{
{
Id: qdrant.NewIDNum(1),
Vectors: qdrant.NewVectors(0.05, 0.61, 0.76, 0.74),
Payload: qdrant.NewValueMap(map[string]any{"city": "Berlin"}),
},
{
Id: qdrant.NewIDNum(2),
Vectors: qdrant.NewVectors(0.19, 0.81, 0.75, 0.11),
Payload: qdrant.NewValueMap(map[string]any{"city": "London"}),
},
{
Id: qdrant.NewIDNum(3),
Vectors: qdrant.NewVectors(0.36, 0.55, 0.47, 0.94),
Payload: qdrant.NewValueMap(map[string]any{"city": "Moscow"}),
},
// Truncated
},
})
if err != nil {
panic(err)
}
fmt.Println(operationInfo)
响应
operation_id=0 status=<UpdateStatus.COMPLETED: 'completed'>
{ operation_id: 0, status: 'completed' }
PointsOperationResponse {
result: Some(
UpdateResult {
operation_id: Some(
0,
),
status: Completed,
},
),
time: 0.00094027,
}
operation_id: 0
status: Completed
{ "operationId": "0", "status": "Completed" }
operation_id:0 status:Acknowledged
运行查询
让我们问一个基本问题 - 我们存储的哪些向量与查询向量 [0.2, 0.1, 0.9, 0.7]
最相似?
search_result = client.query_points(
collection_name="test_collection",
query=[0.2, 0.1, 0.9, 0.7],
with_payload=False,
limit=3
).points
print(search_result)
let searchResult = await client.query(
"test_collection", {
query: [0.2, 0.1, 0.9, 0.7],
limit: 3
});
console.debug(searchResult.points);
use qdrant_client::qdrant::QueryPointsBuilder;
let search_result = client
.query(
QueryPointsBuilder::new("test_collection")
.query(vec![0.2, 0.1, 0.9, 0.7])
)
.await?;
dbg!(search_result);
import java.util.List;
import io.qdrant.client.grpc.Points.ScoredPoint;
import io.qdrant.client.grpc.Points.QueryPoints;
import static io.qdrant.client.QueryFactory.nearest;
List<ScoredPoint> searchResult =
client.queryAsync(QueryPoints.newBuilder()
.setCollectionName("test_collection")
.setLimit(3)
.setQuery(nearest(0.2f, 0.1f, 0.9f, 0.7f))
.build()).get();
System.out.println(searchResult);
var searchResult = await client.QueryAsync(
collectionName: "test_collection",
query: new float[] { 0.2f, 0.1f, 0.9f, 0.7f },
limit: 3,
);
Console.WriteLine(searchResult);
import (
"context"
"fmt"
"github.com/qdrant/go-client/qdrant"
)
searchResult, err := client.Query(context.Background(), &qdrant.QueryPoints{
CollectionName: "test_collection",
Query: qdrant.NewQuery(0.2, 0.1, 0.9, 0.7),
})
if err != nil {
panic(err)
}
fmt.Println(searchResult)
响应
[
{
"id": 4,
"version": 0,
"score": 1.362,
"payload": null,
"vector": null
},
{
"id": 1,
"version": 0,
"score": 1.273,
"payload": null,
"vector": null
},
{
"id": 3,
"version": 0,
"score": 1.208,
"payload": null,
"vector": null
}
]
结果按相似度降序返回。请注意,默认情况下,这些结果中缺少载荷和向量数据。有关如何启用它,请参阅 结果中的载荷和向量。
添加过滤器
我们可以通过按载荷过滤进一步缩小结果范围。让我们找到包含“London”的最接近的结果。
from qdrant_client.models import Filter, FieldCondition, MatchValue
search_result = client.query_points(
collection_name="test_collection",
query=[0.2, 0.1, 0.9, 0.7],
query_filter=Filter(
must=[FieldCondition(key="city", match=MatchValue(value="London"))]
),
with_payload=True,
limit=3,
).points
print(search_result)
searchResult = await client.query("test_collection", {
query: [0.2, 0.1, 0.9, 0.7],
filter: {
must: [{ key: "city", match: { value: "London" } }],
},
with_payload: true,
limit: 3,
});
console.debug(searchResult);
use qdrant_client::qdrant::{Condition, Filter, QueryPointsBuilder};
let search_result = client
.query(
QueryPointsBuilder::new("test_collection")
.query(vec![0.2, 0.1, 0.9, 0.7])
.filter(Filter::must([Condition::matches(
"city",
"London".to_string(),
)]))
.with_payload(true),
)
.await?;
dbg!(search_result);
import static io.qdrant.client.ConditionFactory.matchKeyword;
List<ScoredPoint> searchResult =
client.queryAsync(QueryPoints.newBuilder()
.setCollectionName("test_collection")
.setLimit(3)
.setFilter(Filter.newBuilder().addMust(matchKeyword("city", "London")))
.setQuery(nearest(0.2f, 0.1f, 0.9f, 0.7f))
.setWithPayload(enable(true))
.build()).get();
System.out.println(searchResult);
using static Qdrant.Client.Grpc.Conditions;
var searchResult = await client.QueryAsync(
collectionName: "test_collection",
query: new float[] { 0.2f, 0.1f, 0.9f, 0.7f },
filter: MatchKeyword("city", "London"),
limit: 3,
payloadSelector: true
);
Console.WriteLine(searchResult);
import (
"context"
"fmt"
"github.com/qdrant/go-client/qdrant"
)
searchResult, err := client.Query(context.Background(), &qdrant.QueryPoints{
CollectionName: "test_collection",
Query: qdrant.NewQuery(0.2, 0.1, 0.9, 0.7),
Filter: &qdrant.Filter{
Must: []*qdrant.Condition{
qdrant.NewMatch("city", "London"),
},
},
WithPayload: qdrant.NewWithPayload(true),
})
if err != nil {
panic(err)
}
fmt.Println(searchResult)
响应
[
{
"id": 2,
"version": 0,
"score": 0.871,
"payload": {
"city": "London"
},
"vector": null
}
]
您刚刚进行了向量搜索。您将向量加载到数据库中,并用您自己的向量查询了数据库。Qdrant 找到了最接近的结果,并向您展示了相似度得分。
下一步
现在您知道 Qdrant 如何工作了。Qdrant Cloud 的入门也非常简单。创建一个账户,完全免费使用我们的 SaaS。我们将负责基础设施维护和软件更新。
要了解更多复杂的向量搜索示例,请阅读我们的 教程,并在我们的 示例 的帮助下创建您自己的应用程序。
注意:还有另一种在本地运行 Qdrant 的方法。如果您是 Python 开发者,我们建议您尝试 Qdrant 客户端 中的本地模式,因为它只需要几分钟就可以设置好。