PHP项目怎么实现向量数据库?

wen java案例 1

本文目录导读:

PHP项目怎么实现向量数据库?

  1. 方案一:使用 PostgreSQL + pgvector 扩展(推荐,生产可靠)
  2. 方案二:使用独立的 Vector Database 客户端(如 Qdrant、Milvus)
  3. 方案三:使用 SQLite + sqlite-vec 扩展(适合轻量级/单机)
  4. 方案四:使用 Redis Stack 的向量搜索模块
  5. 总结与选型建议

在 PHP 项目中实现向量数据库,通常有 3 种主流方式,由于 PHP 本身没有原生的向量索引库,需要借助扩展、外部服务或数据库中间件

以下是具体的实现路径和代码示例:

使用 PostgreSQL + pgvector 扩展(推荐,生产可靠)

这是目前 PHP 与向量数据库结合最成熟、最稳定的方式,PostgreSQL 加上 pgvector 扩展后,支持存储向量和进行相似性搜索。

环境准备

  • 安装 PostgreSQL 并启用 pgvector 扩展。
  • 安装 PHP 的 pgsqlPDO_PGSQL 扩展。

创建表和索引

-- 启用扩展
CREATE EXTENSION vector;
-- 创建表,vec 字段定义为 768 维向量(OpenAI 等模型常用)
CREATE TABLE items (
    id SERIAL PRIMARY KEY,
    content TEXT,
    embedding vector(768)
);
-- 创建 IVFFlat 索引(加速搜索,列表数一般为 行数/1000)
CREATE INDEX ON items USING ivfflat (embedding vector_cosine_ops) WITH (lists = 100);

PHP 代码实现

<?php
// 连接数据库
$pdo = new PDO('pgsql:host=localhost;dbname=testdb', 'user', 'pass');
// 1. 插入向量(假设已有嵌入模型返回的数组)
function insertEmbedding(string $text, array $embedding): void
{
    global $pdo;
    $vecStr = '[' . implode(',', $embedding) . ']'; // pgvector 格式
    $stmt = $pdo->prepare('INSERT INTO items (content, embedding) VALUES (?, ?::vector)');
    $stmt->execute([$text, $vecStr]);
}
// 2. 查询相似内容(余弦距离)
function searchSimilar(array $queryEmbedding, int $topK = 5): array
{
    global $pdo;
    $vecStr = '[' . implode(',', $queryEmbedding) . ']';
    // 使用 <=> 余弦距离运算符
    $stmt = $pdo->prepare('SELECT content, 1 - (embedding <=> ?::vector) AS similarity
                           FROM items
                           ORDER BY embedding <=> ?::vector
                           LIMIT ?');
    $stmt->execute([$vecStr, $vecStr, $topK]);
    return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
// 示例用法
$embedding = [0.1, 0.2, 0.3, ...]; // 768 维
insertEmbedding('hello world', $embedding);
$results = searchSimilar([0.11, 0.21, 0.31, ...], 5);

优点:标准 SQL 语法、支持事务、与现有数据无缝集成。
缺点:需要 PostgreSQL 安装 pgvector 扩展(云服务可能有支持限制)。


使用独立的 Vector Database 客户端(如 Qdrant、Milvus)

这些专用向量数据库提供 RESTful 或 gRPC 接口,PHP 通过 HTTP 客户端调用。

安装 Qdrant(推荐轻量级)

docker run -p 6333:6333 qdrant/qdrant

安装 PHP HTTP 客户端

composer require guzzlehttp/guzzle

PHP 代码示例

<?php
require 'vendor/autoload.php';
use GuzzleHttp\Client;
class QdrantVectorDB
{
    private Client $client;
    private string $collection = 'my_collection';
    public function __construct()
    {
        $this->client = new Client(['base_uri' => 'http://localhost:6333']);
    }
    // 创建集合(一次)
    public function createCollection(): void
    {
        $body = [
            'vectors' => ['size' => 768, 'distance' => 'Cosine']
        ];
        $this->client->put("/collections/{$this->collection}", [
            'json' => $body
        ]);
    }
    // 插入点
    public function upsert(int $id, array $vector, array $payload = []): void
    {
        $this->client->put("/collections/{$this->collection}/points", [
            'json' => [
                'points' => [[
                    'id' => $id,
                    'vector' => $vector,
                    'payload' => $payload
                ]]
            ]
        ]);
    }
    // 搜索
    public function search(array $queryVector, int $limit = 5): array
    {
        $response = $this->client->post("/collections/{$this->collection}/points/search", [
            'json' => [
                'vector' => $queryVector,
                'limit' => $limit
            ]
        ]);
        return json_decode($response->getBody(), true);
    }
}
// 使用
$db = new QdrantVectorDB();
$db->createCollection();
$db->upsert(1, [0.1, 0.2, ...], ['content' => 'some text']);
$result = $db->search([0.11, 0.21, ...]);

优点:性能极佳、支持大规模分布式、原生向量索引(HNSW)。
缺点:需要额外维护一个数据库服务,数据与关系型数据库分离。


使用 SQLite + sqlite-vec 扩展(适合轻量级/单机)

如果项目是单机或小型应用,sqlite-vec 是 PHP 可直接集成的向量 SQLite 扩展。

安装 sqlite-vec

# 下载对应平台的 .so/.dll 文件,或通过 composer 加载
composer require aphp/sqlite-vec

PHP 代码

<?php
// 注意:需要加载扩展,不同环境方式不同
$db = new SQLite3('vectors.db');
$db->enableLoadingExtensions();
$db->loadExtension('sqlite_vec.so');  // 动态加载
// 创建虚拟表
$db->exec("CREATE VIRTUAL TABLE IF NOT EXISTS vec_memory USING vec0(
    content VECTOR[768]
)");
// 插入
$stmt = $db->prepare("INSERT INTO vec_memory(rowid, content) VALUES (?, ?)");
$stmt->bindValue(1, 1, SQLITE3_INTEGER);
$stmt->bindValue(2, json_encode([0.1, 0.2, ...]), SQLITE3_TEXT);
$stmt->execute();
// 搜索
$queryVec = json_encode([0.11, 0.21, ...]);
$res = $db->query("SELECT rowid, distance
                   FROM vec_memory
                   WHERE content MATCH ?
                   ORDER BY distance
                   LIMIT 5", $queryVec);

优点:无外部依赖,PHP 进程内运行。
缺点:性能上限低、不适合大数据量(>10万条)、并发差。


使用 Redis Stack 的向量搜索模块

如果项目已经在用 Redis,可以直接启用 redis-stack-server

启动 Redis Stack

docker run -p 6379:6379 redis/redis-stack-server

PHP 代码

<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 创建索引(FT.CREATE)
$redis->rawCommand('FT.CREATE', 'idx:vectors', 'ON', 'HASH', 'PREFIX', '1', 'doc:',
    'SCHEMA', 'title', 'TEXT', 'WEIGHT', '1.0',
    'embedding', 'VECTOR', 'FLAT', '6', 'TYPE', 'FLOAT32', 'DIM', '768', 'DISTANCE_METRIC', 'COSINE');
// 插入
$redis->hSet('doc:1', 'embedding', pack('f*', ...$embeddingArray));
// 搜索(FT.SEARCH)
$query = "*=>[KNN 5 @embedding \$vec AS score]";
$params = ['vec' => pack('f*', ...$queryEmbedding)];
$result = $redis->rawCommand('FT.SEARCH', 'idx:vectors', $query, 'PARAMS', '2', 'vec', $params['vec'], 'SORTBY', 'score', 'LIMIT', '0', '5');

优点:无需新服务、速度快、支持混合搜索。
缺点:Redis 内存消耗大、持久化机制不如专业数据库。


总结与选型建议

场景 推荐方案
已有 PostgreSQL,数据强一致 pgvector(方案一)
要高并发、海量向量(>100万) Qdrant/Milvus(方案二)
单机小应用、不想搭服务 sqlite-vec(方案三)
已用 Redis,内存够用 Redis Stack(方案四)

关键点提醒

  1. 向量生成:PHP 通常需要调用外部 API(如 OpenAI、本地 Python 服务)来生成向量,因为 PHP 没有好用的本地嵌入模型库。
  2. 批量插入:向量数据库建议用事务或批量 API 插入,单条插入性能差。
  3. 索引调优pgvector 的 IVFFlat 需要调 lists 参数,Qdrant 的 HNSW 需要调 ef_construct,否则精确度下降。

建议初学者从 方案二(Qdrant + Guzzle) 开始,逻辑清晰且文档丰富。

抱歉,评论功能暂时关闭!