
docker-compose.yml
version: '3.5'
services:
etcd:
container_name: milvus-etcd
image: quay.io/coreos/etcd:v3.5.0
environment:
- ETCD_AUTO_COMPACTION_MODE=revision
- ETCD_AUTO_COMPACTION_RETENTION=1000
- ETCD_QUOTA_BACKEND_BYTES=4294967296
- ETCD_SNAPSHOT_COUNT=50000
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/etcd:/etcd
command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
minio:
container_name: milvus-minio
image: minio/minio:RELEASE.2022-03-17T06-34-49Z
environment:
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/minio:/minio_data
command: minio server /minio_data --console-address ":9001"
ports:
- "19001:9001"
- "19000:9000"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
standalone:
container_name: milvus-standalone
image: milvusdb/milvus:v2.1.4
command: ["milvus", "run", "standalone"]
environment:
ETCD_ENDPOINTS: etcd:2379
MINIO_ADDRESS: minio:9000
volumes:
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/milvus:/var/lib/milvus
ports:
- "19530:19530"
- "9091:9091"
depends_on:
- "etcd"
- "minio"
networks:
default:
name: milvus
基本使用案例
# hello_milvus.py 展示了 PyMilvus 的基本操作,PyMilvus 是 Milvus 的 Python SDK。
# 1. 连接到 Milvus
# 2. 创建集合(collection)
# 3. 插入数据
# 4. 创建索引
# 5. 在实体上执行搜索、查询和混合搜索
# 6. 通过 PK 删除实体
# 7. 删除集合
import time
import numpy as np
from pymilvus import (
connections,
utility,
FieldSchema, CollectionSchema, DataType,
Collection,
)
fmt = "\n=== {:30} ===\n"
search_latency_fmt = "搜索延迟 = {:.4f}秒"
num_entities, dim = 3000, 8
#################################################################################
# 1. 连接到 Milvus
# 为位于 `localhost:19530` 的 Milvus 服务器添加一个新的连接别名 `default`
# 实际上,“default” 别名是 PyMilvus 中的内建别名。
# 如果 Milvus 的地址与 `localhost:19530` 相同,你可以省略所有
# 参数并调用该方法: `connections.connect()`。
#
# 注意:以下方法的 `using` 参数默认为 "default"。
print(fmt.format("开始连接到 Milvus"))
connections.connect("default", host="124.222.68.249", port="29530")
has = utility.has_collection("hello_milvus")
print(f"Milvus 中是否存在 hello_milvus 集合: {has}")
#################################################################################
# 2. 创建集合
# 我们将创建一个包含 3 个字段的集合。
# +-+------------+------------+------------------+------------------------------+
# | | 字段名 | 字段类型 | 其他属性 | 字段描述 |
# +-+------------+------------+------------------+------------------------------+
# |1| "pk" | VarChar | is_primary=True | "主键字段" |
# | | | | auto_id=False | |
# +-+------------+------------+------------------+------------------------------+
# |2| "random" | Double | | "一个双精度字段" |
# +-+------------+------------+------------------+------------------------------+
# |3|"embeddings"| FloatVector| dim=8 | "维度为 8 的浮点向量字段" |
# +-+------------+------------+------------------+------------------------------+
fields = [
FieldSchema(name="pk", dtype=DataType.VARCHAR, is_primary=True, auto_id=False, max_length=100),
FieldSchema(name="random", dtype=DataType.DOUBLE),
FieldSchema(name="embeddings", dtype=DataType.FLOAT_VECTOR, dim=dim)
]
schema = CollectionSchema(fields, "hello_milvus 是最简单的 demo,用于介绍 APIs")
print(fmt.format("创建集合 `hello_milvus`"))
hello_milvus = Collection("hello_milvus", schema, consistency_level="Strong")
################################################################################
# 3. 插入数据
# 我们将向 `hello_milvus` 插入 3000 行数据
# 待插入的数据必须按字段组织。
#
# insert() 方法返回:
# - 如果 schema 中的 auto_id=True,则由 Milvus 自动生成的主键;
# - 如果 schema 中的 auto_id=False,则实体中现有的主键字段。
print(fmt.format("开始插入实体"))
rng = np.random.default_rng(seed=19530)
entities = [
# 由于 `auto_id` 设置为 False,提供 pk 字段
[str(i) for i in range(num_entities)],
rng.random(num_entities).tolist(), # 字段 random, 仅支持列表
rng.random((num_entities, dim)), # 字段 embeddings, 支持 numpy.ndarray 和列表
]
insert_result = hello_milvus.insert(entities)
print(f"Milvus 中的实体数量: {hello_milvus.num_entities}") # 检查 num_entites
################################################################################
# 4. 创建索引
# 我们将为 hello_milvus 集合创建一个 IVF_FLAT 索引。
# create_index() 只能应用于 `FloatVector` 和 `BinaryVector` 字段。
print(fmt.format("开始创建 IVF_FLAT 索引"))
index = {
"index_type": "IVF_FLAT",
"metric_type": "L2",
"params": {"nlist": 128},
}
hello_milvus.create_index("embeddings", index)
################################################################################
# 5. 搜索、查询和混合搜索
# 在数据插入 Milvus 并建立索引后,你可以执行:
# - 基于向量相似性的搜索
# - 基于标量过滤(布尔值,整数等)的查询
# - 基于向量相似性和标量过滤的混合搜索。
#
# 在执行搜索或查询之前,你需要将 `hello_milvus` 中的数据加载到内存中。
print(fmt.format("开始加载"))
hello_milvus.load()
# -----------------------------------------------------------------------------
# 基于向量相似性的搜索
print(fmt.format("开始基于向量相似性的搜索"))
vectors_to_search = entities[-1][-2:]
search_params = {
"metric_type": "L2",
"params": {"nprobe": 10},
}
start_time = time.time()
result = hello_milvus.search(vectors_to_search, "embeddings", search_params, limit=3, output_fields=["random"])
end_time = time.time()
for hits in result:
for hit in hits:
print(f"命中: {hit}, random 字段: {hit.entity.get('random')}")
print(search_latency_fmt.format(end_time - start_time))
# -----------------------------------------------------------------------------
# 基于标量过滤的查询(布尔值,整数等)
print(fmt.format("开始执行 `random > 0.5` 的查询"))
start_time = time.time()
result = hello_milvus.query(expr="random > 0.5", output_fields=["random", "embeddings"])
end_time = time.time()
print(f"查询结果:\n-{result[0]}")
print(search_latency_fmt.format(end_time - start_time))
# -----------------------------------------------------------------------------
# 混合搜索
print(fmt.format("开始执行 `random > 0.5` 的混合搜索"))
start_time = time.time()
result = hello_milvus.search(vectors_to_search, "embeddings", search_params, limit=3, expr="random > 0.5", output_fields=["random"])
end_time = time.time()
for hits in result:
for hit in hits:
print(f"命中: {hit}, random 字段: {hit.entity.get('random')}")
print(search_latency_fmt.format(end_time - start_time))
###############################################################################
# 6. 通过 PK 删除实体
# 你可以使用布尔表达式通过其 PK 值删除实体。
ids = insert_result.primary_keys
expr = f'pk in ["{ids[0]}" , "{ids[1]}"]'
print(fmt.format(f"开始执行 expr `{expr}` 的删除"))
result = hello_milvus.query(expr=expr, output_fields=["random", "embeddings"])
print(f"通过 expr=`{expr}` 删除前的查询 -> 结果: \n-{result[0]}\n-{result[1]}\n")
hello_milvus.delete(expr)
result = hello_milvus.query(expr=expr, output_fields=["random", "embeddings"])
print(f"通过 expr=`{expr}` 删除后的查询 -> 结果: {result}\n")
###############################################################################
# 7. 删除集合
# 最后,删除 hello_milvus 集合
print(fmt.format("删除集合 `hello_milvus`"))
utility.drop_collection("hello_milvus")
version: '3.5'
services:
etcd:
container_name: milvus-etcd
image: quay.io/coreos/etcd:v3.5.0
environment:
- ETCD_AUTO_COMPACTION_MODE=revision
- ETCD_AUTO_COMPACTION_RETENTION=1000
- ETCD_QUOTA_BACKEND_BYTES=4294967296
- ETCD_SNAPSHOT_COUNT=50000
volumes:
- etcd_data:/etcd
command: etcd -advertise-client-urls=http://127.0.0.1:2379 -listen-client-urls http://0.0.0.0:2379 --data-dir /etcd
minio:
container_name: milvus-minio
image: minio/minio:RELEASE.2022-03-17T06-34-49Z
environment:
MINIO_ACCESS_KEY: minioadmin
MINIO_SECRET_KEY: minioadmin
volumes:
- minio_data:/minio_data
command: minio server /minio_data --console-address ":9001"
ports:
- "19001:9001"
- "19000:9000"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
interval: 30s
timeout: 20s
retries: 3
standalone:
container_name: milvus-standalone
image: milvusdb/milvus:v2.2.9
command: ["milvus", "run", "standalone"]
environment:
ETCD_ENDPOINTS: etcd:2379
MINIO_ADDRESS: minio:9000
volumes:
- milvus_data:/var/lib/milvus
ports:
- "19530:19530"
- "9091:9091"
depends_on:
- "etcd"
- "minio"
networks:
default:
name: milvus
volumes:
etcd_data:
minio_data:
milvus_data: