本文目录导读:

- 使用专用向量数据库(最推荐)
- PostgreSQL + pgvector 扩展(性价比最高)
- Elasticsearch + 向量插件(适合已有ES的场景)
- 纯PHP实现(仅适用于小数据量)
- 推荐选择建议
- 向量生成注意事项
在PHP项目中实现向量检索,通常有以下几种方案,按推荐程度排序:
使用专用向量数据库(最推荐)
Milvus + PHP 客户端
// 安装: composer require milvus-php/milvus-php
use Milvus\Client;
use Milvus\Collection;
$client = new Client(['host' => 'localhost', 'port' => 19530]);
// 创建集合
$collection = new Collection($client, 'documents');
$collection->create([
'fields' => [
['name' => 'id', 'type' => 'int64', 'primary_key' => true],
['name' => 'vector', 'type' => 'float_vector', 'params' => ['dim' => 768]],
['name' => 'text', 'type' => 'varchar', 'max_length' => 1000],
]
]);
// 插入向量数据
$vectors = [[0.1, 0.2, ...], [0.3, 0.4, ...]]; // 768维向量
$collection->insert([
['id' => 1, 'vector' => $vectors[0], 'text' => '文档1'],
['id' => 2, 'vector' => $vectors[1], 'text' => '文档2'],
]);
// 向量检索
$results = $collection->search([
'vector' => [0.15, 0.25, ...],
'anns_field' => 'vector',
'limit' => 10,
'metric_type' => 'COSINE'
]);
Qdrant + PHP 客户端
// 安装: composer require qdrant/php-client
use Qdrant\Client;
$client = new Client('http://localhost:6333');
// 创建集合
$client->collections()->create('documents', [
'vectors' => [
'size' => 768,
'distance' => 'Cosine'
]
]);
// 插入点
$client->points()->upsert('documents', [
'points' => [
['id' => 1, 'vector' => [0.1, 0.2, ...], 'payload' => ['text' => '文档1']],
['id' => 2, 'vector' => [0.3, 0.4, ...], 'payload' => ['text' => '文档2']],
]
]);
// 搜索
$results = $client->points()->search('documents', [
'vector' => [0.15, 0.25, ...],
'limit' => 10
]);
Weaviate + PHP
// 安装: composer require flow-php/weaviate-schema-manager
use Weaviate\Client;
$client = Client::withApiKey('your-api-key', 'https://your-instance.weaviate.io');
// 创建Schema
$client->schema()->createClass([
'class' => 'Document',
'vectorizer' => 'none', // 使用自定义向量
'properties' => [
['name' => 'text', 'dataType' => ['text']],
]
]);
// 插入数据
$client->data()->create([
'class' => 'Document',
'properties' => ['text' => '文档内容'],
'vector' => [0.1, 0.2, ...]
]);
// 向量搜索
$results = $client->graphql()->raw('
{
Get {
Document(nearVector: {vector: [0.15, 0.25, ...]}, limit: 10) {
text
_additional { distance }
}
}
}
');
PostgreSQL + pgvector 扩展(性价比最高)
// 需要PostgreSQL + pgvector扩展
// 安装: composer require doctrine/dbal
$conn = new PDO('pgsql:host=localhost;dbname=test', 'user', 'password');
// 创建表和索引(需在数据库中执行)
$conn->exec("
CREATE TABLE documents (
id SERIAL PRIMARY KEY,
text TEXT,
vector vector(768)
);
CREATE INDEX ON documents USING ivfflat (vector vector_cosine_ops);
");
// 插入数据
$stmt = $conn->prepare("INSERT INTO documents (text, vector) VALUES (?, ?)");
$stmt->execute(['文档1', json_encode([0.1, 0.2, ...])]);
// 向量检索
$queryVector = json_encode([0.15, 0.25, ...]);
$stmt = $conn->prepare("
SELECT text, vector <=> ?::vector AS distance
FROM documents
ORDER BY vector <=> ?::vector
LIMIT 10
");
$stmt->execute([$queryVector, $queryVector]);
$results = $stmt->fetchAll();
Elasticsearch + 向量插件(适合已有ES的场景)
// 安装: composer require elasticsearch/elasticsearch
$client = Elastic\Elasticsearch\ClientBuilder::create()
->setHosts(['localhost:9200'])
->build();
// 创建索引
$client->indices()->create([
'index' => 'documents',
'body' => [
'mappings' => [
'properties' => [
'vector' => [
'type' => 'dense_vector',
'dims' => 768,
'index' => true,
'similarity' => 'cosine'
],
'text' => ['type' => 'text']
]
]
]
]);
// 插入数据
$client->index([
'index' => 'documents',
'body' => [
'text' => '文档1',
'vector' => [0.1, 0.2, ...]
]
]);
// 向量搜索
$results = $client->search([
'index' => 'documents',
'body' => [
'knn' => [
'field' => 'vector',
'query_vector' => [0.15, 0.25, ...],
'k' => 10,
'num_candidates' => 100
]
]
]);
纯PHP实现(仅适用于小数据量)
class VectorSearch {
public static function cosineSimilarity(array $vec1, array $vec2): float {
$dotProduct = 0;
$norm1 = 0;
$norm2 = 0;
for ($i = 0; $i < count($vec1); $i++) {
$dotProduct += $vec1[$i] * $vec2[$i];
$norm1 += $vec1[$i] ** 2;
$norm2 += $vec2[$i] ** 2;
}
return $dotProduct / (sqrt($norm1) * sqrt($norm2));
}
public static function search(array $vectors, array $query, int $k = 10): array {
$scores = [];
foreach ($vectors as $id => $vector) {
$scores[$id] = self::cosineSimilarity($query, $vector);
}
arsort($scores);
return array_slice($scores, 0, $k, true);
}
}
// 使用示例
$vectors = [
1 => [0.1, 0.2, 0.3],
2 => [0.4, 0.5, 0.6],
// ...
];
$query = [0.15, 0.25, 0.35];
$results = VectorSearch::search($vectors, $query, 10);
推荐选择建议
| 场景 | 推荐方案 | 理由 |
|---|---|---|
| 新项目 | pgvector | 成本低,维护简单,功能足够 |
| 大规模(>1000万) | Milvus | 性能最好,支持分布式 |
| 已有ES | ES向量搜索 | 无需新增基础设施 |
| 小数据(<10万) | 纯PHP实现 | 无额外依赖,简单快速 |
向量生成注意事项
无论使用哪种方案,都需要提前生成向量:
// 使用 OpenAI embedding
function getEmbedding(string $text): array {
$response = file_get_contents('https://api.openai.com/v1/embeddings', false,
stream_context_create([
'http' => [
'method' => 'POST',
'header' => "Content-Type: application/json\r\nAuthorization: Bearer YOUR_API_KEY",
'content' => json_encode(['model' => 'text-embedding-ada-002', 'input' => $text])
]
])
);
$data = json_decode($response, true);
return $data['data'][0]['embedding'];
}
推荐从 pgvector 开始,成本最低且功能完善,后续可根据需要迁移到专业的向量数据库。
版权声明:足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
足球直播
足球直播
足球直播
足球直播
足球直播
中超直播
中超直播
中超直播
中超直播
中超直播
英超直播
英超直播
英超直播
英超直播
英超直播
德甲直播
德甲直播
德甲直播
德甲直播
德甲直播
西甲直播
西甲直播
西甲直播
西甲直播
西甲直播
意甲直播
意甲直播
意甲直播
意甲直播
意甲直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播